[초보]채팅 프로그램에서 클라이언트쪽 키보드 입력처리에 관한
글쓴이: iamsjkim / 작성시간: 금, 2003/10/10 - 9:03오후
프로그램 초보 질문입니다..
리눅스 환경이고 gcc 컴파일 입니다..
클라이언트가 유저로부터의 키보드 입력을 select문에서 받아 적절한 function수행 후에 서버에게로 보내주면 서버가 그 메세지에 적절한 작업수행후 클라이언트에게 보내고, 클라이언트는 서버로부터 오는 메세지는 받아다가 유저에게 출력해주는 채팅 서버-클라이언트 프로그램과 유사한 프로그램이 필요해서 일단 채팅프로그램 비스무리한 코드를 작성 해봤습니다.
그런데 서버쪽 실행코드를 실행시켜놓고 클라이언트도 실행시킨 후에 클라이언트쪽 터미널에서 몇글자 친 다음에 엔터를 치면 일단 메세지는 대충 서버에게 전달이 되는것 같은데 서버에서 작업을 수행한 후 해당 클라이언트에게 send를 하면 클라이언트쪽에서는 아무 반응이 없습니다. -.-
게다가 제가 몇글자(예를 들어 0000)을 치고 <Enter>를 치면 같은 메세지가 서버에게 두번 전송되기까지 하고 서버가 보내는 메세지는 받지도 않고 계속 유저의 키보드 입력만 기다립니다.
대체 어디에 문제가 있는건지 모르겠습니다.
처음에 read함수 말고 recv함수를 썼더니 키보드 입력도 전혀 안먹히기에 read함수로 바꿨더니 위와 같은 문제가 생깁니다.
제가 키보드에 입력하는 방법에 문제가 있는건지요?
답변 부탁드립니다.. T_T
일단 코드의 골격은 대충 다음과 같습니다.
Server쪽 코드 :
int main() { fd_set allset; ....... ....... FD_ZERO(&allset); FD_SET(server_fd,&allset); ....... ....... while(1) { nready = select(max_fd+1,&allset,NULL,NULL,NULL); if(FD_ISSET(server_fd,&allset)) { client_fd = accept(server_fd, (struct sockaddr *) &client_addr, &clilen); ....... FD_SET(client_fd,&allset); /* add new descriptor to set */ ....... } for(i=0;i<(max_i+1); i++) /* check all clients for data */ { if((sock_fd = client_s[i]) < 0) continue; if(FD_ISSET(sock_fd,&allset)) { size = recv(sock_fd, rbuf, MAXLINE, 0); ....... ....... } } }
Client쪽 코드 :
int main() { ....... fd_set read_fds; ....... FD_ZERO(&read_fds); FD_SET(serverFd,&read_fds); /* server input */ FD_SET(0,&read_fds); /* standard input */ ....... while(1) { nready = select(serverFd+1,&read_fds,NULL,NULL,NULL); if(FD_ISSET(0,&read_fds)) /* standard input : user input */ { size = read(0,(char *)rbuf,8,0)); ....... ....... } if(FD_ISSET(serverFd,&read_fds)) /* server input */ { size = recv(serverFd, rbuf, MAXDATASIZE, 0); ....... ....... } }
Forums:
[quote="iamsjkim"]서버가 보내는 메세지는 받지도 않고
키보드 입력함수에서 블럭(다음을 실행하지 않고 기다리는)이 걸린것 같군요.
입력과 수신을 두개의 쓰레드로 만드세요.
그나저나 백수 언제 탈출하냐... ㅡㅡ; 배고파라.
select에 등록하는 디스크립터 세팅이 잘못...
여기서 FD_SET을 잘못 이해하셔서 그런겁니다.
FD_SET에 의해 마스킹된(디스크립터를 등록하는 거죠) 비트는
select 한번 거쳐서 읽고 나면 마스킹이 지워집니다.
그래서 select를 한번 거치고 난후 그 디스크립터를
다시 셀렉트가 관찰해야 한다면 다시 세팅을 해야하죠.
결국 FD_ZERO나 FD_SET을 while()내부로 옮겨야한다는 겁니다.
서버나 클라이언트 쪽 모두 잘못 세팅되있습니다.
도움이 되시길..
Do you think that's the air you are breathing now?
아, select가 그런줄 모르고.. ^^;;원래 서버쪽 코드는 아래
아, select가 그런줄 모르고.. ^^;;
원래 서버쪽 코드는 아래와 같았는데 여기에 올릴적에는 read_fds와 allset에 차이가 없는줄 알고 그냥 전부 allset으로 통일해서 올려버렸네요..-_-;;;;(서버쪽 코드짤적에 스티븐 아저씨의 네트워크 프로그래밍에 나온 예제를 따라서 짰었는데 fd_set타입 변수가 두개길래 이유도 모르고 그냥 두개로 만들어서 짰었는데 이제야 그 이유를 알겠습니다..감사합니다^ㅡ^)
클라이언트쪽 예제는 스티븐아저씨 책에선 찾을수가 없어서(있는데 제가 못찾은건지도..-_-; ) 제맘대루 짰더니 여지없이 문제가 생기는군요ㅠ_ㅠ(에효..)
쓰레드를 쓰지않은 문제도 생기네요..(쓰레드는 너무 어려워서 타이머 쓰레드만 쓸라고 남겨놨었는데..ㅠ.ㅠ)
다시 코딩해보고 질문 드리겠습니다..
서버쪽 코드 :
답변 달아주신 두분께 정말 감사드립니다. (_ _)~꾸벅
참고로... 두개의 쓰레드로 하지않고표준입력(stdin)을 sel
참고로...
두개의 쓰레드로 하지않고
표준입력(stdin)을 select에 넣을 수 있는 걸로 알고 있습니다.
참고하시기 바랍니다.
그나저나 백수 언제 탈출하냐... ㅡㅡ; 배고파라.
감사합니다(_ _)~
클라이언트쪽 select세팅을 server처럼 바꿔줬더니 제대로 돌아갑니다.(뿌듯^^)
조언말씀 주신 두분께 정말 감사드립니다.
댓글 달기