유닉스 select 와 파이프를 이용해서 서버,클라이언트 채팅 프로그램을 만들고 있습니다.

skynsn3423의 이미지

소켓을 아직 배우지 않아. 소켓 개념은 없구요. 파이프를 이용해서 서버를 통하여 할수 있다면 n명의 사람이 들어와도 채팅을 하게 하고싶습니다.
argv[1] 번으로 ID를 받아 그 ID로 소켓을 만들어 server에서 는 그 ID 명으로 파이프를 만들고, 클라이언트도 argv[1]로 파이프를 만들게 하여, 양방향 통신을 하려고 했는데 ㅠ 막혔습니다 ㅠ
/******* server **********/

#include
#include
#include
#include
#include
#include
#include
#include
#define MSG_SIZE 1024

int main(int argc)
{
char *fifo1 = " ";
char *fifo2 = "cara2server";
char snd_buf[MSG_SIZE];
char rcv_buf[MSG_SIZE];
char msg_header[MSG_SIZE];
int hd_length;
int rfd;
int sfd;
char name[BUFSIZ];
fd_set master_set, read_set;
int rd_cnt,n;
if (argc != 1) {
exit(1);
}
if (mkfifo(fifo2, 0666) == -1) {
if (errno != EEXIST) {
fprintf(stderr, "Error in mkfifo %s\n", fifo2);
exit(3);
}
}
if ((rfd = open(fifo2, O_RDONLY)) < 0) {
fprintf(stderr, "Error in open %s\n", fifo2);
exit(4);
}
// fprintf(stderr, "Error in open %s\n", fifo1);
// exit(5);
// }
// if( 0 < rfd )
// {
// printf("???");
// n = read(rfd,name,BUFSIZ);
// printf("n= %d\n",n);
//
// name[n] = '\0';
// // fscanf(&rfd, "%s",name);
// // printf("%s",n);
// printf("name : %s",name);
// printf("???");
//
// }
// else
// {
// printf(" 클라이언트 접속에 실패 하였습니다.");
// }
// printf(" 클라이언트 접속하였습니다.");
// if(mkfifo(fifo1,066) == -1)
// {
// if(errno != EEXIST)
// {
// //
// fprintf(stderr, "Error in mkfifo %s\n", fifo2);
// exit(2);
// }
// }
// if ((sfd = open(fifo1, O_WRONLY)) <0){
// fprintf(stderr, "Error in open %s\n",fifo1);
// exit(5);
// }
FD_ZERO(&master_set);
FD_SET(0, &master_set);
FD_SET(rfd, &master_set);
while (read_set = master_set, select(sfd+1, &read_set, NULL, NULL, NULL) > 0)
{ // sfd + 1
if (FD_ISSET(0, &read_set)) {
if ((rd_cnt = read(0, snd_buf, MSG_SIZE)) <= 0) {
fprintf(stderr, "Error in read from stdin\n");
exit(6);
}
else {
if (write(sfd, msg_header, hd_length) != hd_length) {
fprintf(stderr, "Error in write to fifo\n");
exit(7);
}
if (write(sfd, snd_buf, rd_cnt) != rd_cnt) {
fprintf(stderr, "Error in write to fifo\n");
exit(7);
}
}
}

if (FD_ISSET(rfd, &read_set))
{
if ((rd_cnt = read(rfd, rcv_buf, MSG_SIZE)) <= 0)
{
fprintf(stderr, "Error in read from fifo\n");
exit(8);
}
else
{
if (write(1, rcv_buf, rd_cnt) != rd_cnt)
{
fprintf(stderr, "Error in write to stdout\n");
exit(9);
}
}
}
}
}

/*********** 클라이언트 ************/
#include
#include
#include
#include
#include
#include
#include
#include
#define MSG_SIZE 1024

int main(int argc, char *argv[])
{
char *fifo1 = argv[1];
char *fifo2 = "cara2server";
char snd_buf[MSG_SIZE];
char rcv_buf[MSG_SIZE];
char msg_header[MSG_SIZE];
int hd_length;
int rfd;
int sfd;
char name[4];
fd_set master_set, read_set;
int rd_cnt;
if (argc != 2) {
printf("usage: %s user_name \n", argv[0]);
exit(1);
}
memset(msg_header, 0, MSG_SIZE);
sprintf(msg_header, "%s : ", argv[1]);
hd_length = strlen(msg_header);

if (mkfifo(fifo1, 0666) == -1) {
if (errno != EEXIST) {
fprintf(stderr, "Error in mkfifo %s\n", fifo1);
exit(2);
}
}
if (mkfifo(fifo2, 0666) == -1) {
if (errno != EEXIST) {
fprintf(stderr, "Error in mkfifo %s\n", fifo2);
exit(3);
}
}
if ((sfd = open(fifo2, O_WRONLY)) < 0) { // blocking until open for reading
fprintf(stderr, "Error in open %s\n", fifo2);
exit(5);
}
if ((rfd = open(fifo1, O_RDONLY)) < 0) {
fprintf(stderr, "Error in open %s\n", fifo1);
exit(4);
}
FD_ZERO(&master_set);
FD_SET(0, &master_set);
FD_SET(rfd, &master_set);
while (read_set = master_set, select(rfd+1, &read_set, NULL, NULL, NULL) > 0) { // rfd + 1
if (FD_ISSET(0, &read_set)) {
if ((rd_cnt = read(0, snd_buf, MSG_SIZE)) <= 0) {
fprintf(stderr, "Error in read from stdin\n");
exit(6);
}
else {
if (write(sfd, msg_header, hd_length) != hd_length) {
fprintf(stderr, "Error in write to fifo\n");
exit(7);
}
if (write(sfd, snd_buf, rd_cnt) != rd_cnt) {
fprintf(stderr, "Error in write to fifo\n");
exit(7);
}
}
}

if (FD_ISSET(rfd, &read_set)) {
if ((rd_cnt = read(rfd, rcv_buf, MSG_SIZE)) <= 0) {
fprintf(stderr, "Error in read from fifo\n");
exit(8);
}
else {
if (write(1, rcv_buf, rd_cnt) != rd_cnt) {
fprintf(stderr, "Error in write to stdout\n");
exit(9);
}
}
}
}
}

클라이언트에서 아이디를 입력해서 서버에서 그 아이디 명을 read 나 fscanf 나.. 이런걸로 읽어서, 클라이언트처럼 *fifo1 = 클라이언트 ID(argv[1]
을 넣어줘서.. 받은 채팅을 3명이 들어오면 3명한테 뿌리려고 합니다. 그런데 일단 군데 군데 주석 된부분 printf 출력문을 넣어봐도 세그멘테이션 오류만 뜨면서..
서버에서 출력 조차 안되고 있습니다 ㅠ 잘못된 부분좀 부탁드려요 ㅠ

shint의 이미지

//
인터넷에서 오류 코드나 예제 소스를 검색 해보시면 이런저런 정보를 얻으실 수 있습니다.

//
한빛 미디어. 한글판 유닉스 시스템 프로그래밍 SVR4 에서 414p 415p 내용을 보니까.
알 수 있을거 같습니다.

답도 알려드리고 싶지만. 책을 한번 보시는것도 좋을거 같습니다.
가격도 2만 4천원이라 저렴하고 한글이라 보기도 쉽고 좋습니다.

//
perror()로 확인해보니. 에러를 알 수 있었습니다.
http://linux.die.net/man/3/perror

Device or resource busy 라고 합니다.

순서는
[server]
unlink(fifoname)
mkfifo(fifoname)
open(fifoname, rd)
read()
write()

[client]
open(fifoname, wr)
read()
write()

이런 방식으로 하나 봅니다.

사용하신 헤더는 이와 같습니다.

//http://linux.die.net/man/3/mkfifo
//http://linux.die.net/man/2/open
//http://linux.die.net/man/3/errno
//http://linux.die.net/man/2/read

세그먼테이션 오류(Segmentaion Fault)
http://cafe.naver.com/embword/41
http://cafe.naver.com/luv2u/29
POSIX Thread 실행시 세그먼트 오류 질문입니다
http://cafe.naver.com/linuxcare/4838
http://cafe.naver.com/carroty/208348
http://diarynoranf.tistory.com/498
http://blog.naver.com/youtoo2?Redirect=Log&logNo=20007002508
http://kldp.org/node/31986

#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <io.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
 
 
server                          client
 
               <----------      ID
 
      ID pipe  ----------->     ID pipe
               <-----------     
 
      socket create()
 
      read() or fscanf()
      socket list() each send()
      socket list() each send()
      socket list() each send()

실행해서 접속해보니. 클라리언트가 역'으로 해킹 당하는것도 가능해 보이네요. ㅇ_ㅇ;;

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.