가위바위보 게임(클라이언트대 클라이언트)???

namola의 이미지

가위바위보 게임(클라이언트대 클라이언트)을
구현해 보았는데...처음 각각 2개의 클라이언트가
접속하여 게임을 하면...잘돼는데..그리고 종료가
된다음에 다시 접속하게 되면...잘 안됩니다.
이유가 무엇일까요?
답변 부탁드리겠습니다.
다음은 서버 코드 입니다.

/* 
* ipcgame_serv.c 
* Written by CH. Yoo 
*/ 
#include <stdio.h> 
#include <unistd.h> 
#include <signal.h> 
#include 
#include 
#include 
#include 

#define BUFSIZE 100 

void error_handling(char *message); 
void z_handler(int sig); 
int who_win(int a,int b); 

int main(int argc, char **argv) 
{ 
int fd1[2],fd2[2]; 

char buffer[BUFSIZE]; 
char intro[]="입력하세요(가위:0 바위:1 보:2) : "; 
/* 바이트 비교시 48,49,50 */ 
char win[]="축하합니다. 당신이 이겼습니다.\n"; 
char lose[]="안타깝게도 졌네요.\n"; 
char no_winner[]="비겼네요. 승자가 없습니다. \n"; 

int serv_sock; 
int clnt_sock; 

struct sockaddr_in serv_addr; 
struct sockaddr_in clnt_addr; 
struct sigaction act; 
int str_len, state, addr_size,clnt_num;/*clnt_num 추가*/ 
pid_t pid; 

if(argc!=2) { 
printf("Usage : %s \n", argv[0]); 
exit(1); 
} 

if(pipe(fd1)==-1||pipe(fd2)==-1)/*두개의 파이프 생성*/ 
error_handling("pipe() error"); 

act.sa_handler=z_handler;/*시그널 핸들링을 위한 핸들러 설정*/ 
sigemptyset(&act.sa_mask); 
act.sa_flags=0; 

state=sigaction(SIGCHLD, &act, 0);/*시그널 핸들러 등록*/ 
if(state==-1) 
error_handling("sigaction() error"); 

serv_sock=socket(PF_INET,SOCK_STREAM,0); 
if(serv_sock==-1) 
error_handling("socket() error"); 

memset(&serv_addr,0,sizeof(serv_addr)); 
serv_addr.sin_family=AF_INET; 
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY); 
serv_addr.sin_port=htons(atoi(argv[1])); 

if(bind(serv_sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1) 
error_handling("bind() error"); 

if(listen(serv_sock,5)==-1) 
error_handling("listen() error"); 

clnt_num=0;/*0으로 초기화*/ 

while(1) { 
addr_size=sizeof(clnt_addr); 

clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_addr,&addr_size); 
if(clnt_sock==-1) 
continue; 


if( (pid=fork()) == -1) { /*fork 실패시*/ 
close(clnt_sock); 
continue; 
} 
else if (pid > 0) { /*부모프로세스 실행 영역*/ 
int result; 
puts("연결 생성"); 
close(clnt_sock); 

if(clnt_num==0) { 
clnt_num++; 
continue; 
} 

read(fd1[0],&buffer[0],BUFSIZE-1);/*첫번째 클라이언트 수신*/ 
read(fd1[0],&buffer[1],BUFSIZE-1);/*두번째 클라이언트 수신*/ 

result = who_win(buffer[0],buffer[1]); 
if(result==0) { /*비긴경우*/ 
buffer[2]=0; 
buffer[3]=0; 
buffer[4]=0; 
write(fd2[1],buffer,sizeof(buffer)); 
write(fd2[1],buffer,sizeof(buffer)); 
} 
else if (result == 1) { /* 이긴경우 */ 
buffer[2]=1; 
buffer[3]=-1; 
buffer[4]=0; 
write(fd2[1],buffer,sizeof(buffer)); 
write(fd2[1],buffer,sizeof(buffer)); 
} 
else { /* 진경우*/ 
buffer[2]=-1; 
buffer[3]=1; 
buffer[4]=0; 
write(fd2[1],buffer,sizeof(buffer)); 
write(fd2[1],buffer,sizeof(buffer)); 
} 
} 
else { /* chlid process zone */ 
close(serv_sock); 
char temp; 

write(clnt_sock,intro,sizeof(intro)); 
read(clnt_sock,buffer,BUFSIZE); /*클라이언트 선택 수신*/ 
write(fd1[1],buffer,1);/*부모프로세스로 선택 전송*/ 
temp=buffer[0]; 
read(fd2[0],buffer,BUFSIZE); 

temp = (temp==buffer[0]) ? buffer[2] : buffer[3]; 

if(temp==0) 
write(clnt_sock,no_winner,sizeof(no_winner)); 
else if (temp==1) 
write(clnt_sock,win,sizeof(win)); 
else 
write(clnt_sock,lose,sizeof(lose)); 

puts("연결 종료"); 
close(clnt_sock); 
clnt_num--; 
exit(0); 
} 
} 
return 0; 
} 

void z_handler(int sig) 
{ 
pid_t pid; 
int rtn; 

pid=waitpid(-1,&rtn,WNOHANG); 
printf("소멸된 좀비의 프로세스 ID : %d \n", pid); 
printf("리턴된 데이터 : %d \n\n", WEXITSTATUS(rtn)); 
} 

int who_win(int a, int b) 
{ 
if(a==b) 
return 0; 
else if(a%3==(b+1)%3) 
return 1; 
else 
return -1; 
} 

void error_handling(char *message) 
{ 
fputs(message,stderr); 
fputc('\n',stderr); 
exit(1); 
} 

다음은 클라이언트 코드입니다.
#include <stdio.h> 
#include <unistd.h> 
#include 
#include 
#include 

#define BUFSIZE 100 

void error_handling(char *message); 

int main(int argc, char **argv) 
{ 
int sock; 
char message[BUFSIZE]; 
int str_len; 

struct sockaddr_in serv_addr; 

if(argc!=3) { 
printf("Usage : %s \n", argv[0]); 
exit(1); 
} 

sock=socket(PF_INET,SOCK_STREAM,0); 
if(sock==-1) 
error_handling("socket() error"); 

memset(&serv_addr,0,sizeof(serv_addr)); 
serv_addr.sin_family=AF_INET; 
serv_addr.sin_addr.s_addr=inet_addr(argv[1]); 
serv_addr.sin_port=htons(atoi(argv[2])); 

if(connect(sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1) 
error_handling("connect() error"); 

/* 가위,바위,보 game start */ 
str_len=read(sock,message,BUFSIZE-1); 
message[str_len]=0; 
fputs(message,stdout); 
fflush(stdout); 

str_len=read(0,message,BUFSIZE); 
write(sock,message,str_len); 

str_len=read(sock,message,BUFSIZE-1); 
message[BUFSIZE]=0; 
puts(message); 

close(sock); 
return 0; 
} 

void error_handling(char *message) 
{ 
fputs(message,stderr); 
fputc('\n',stderr); 
exit(1); 
}

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.