c로 만든 간단한 채팅 서버 소스 이해가 잘 않되서요.
글쓴이: boardholic / 작성시간: 월, 2004/12/20 - 8:52오후
#include <stdio.h> #include <fcntl.h> #include <stdlib.h> #include <signal.h> #include <sys/socket.h> #include <sys/file.h> #include <netinet/in.h> #include <string.h> #define MAXLINE 512 #define MAX_SOCK 64 char *escapechar = "exit"; int getmax(int); void removeClient(int); int maxfdp1; int num_chat = 0; int client_s[FD_SETSIZE]; int main(int argc, char *argv[]) { char rline[MAXLINE], my_msg[MAXLINE]; char *start = "Connected to chat_server \n"; int i, j, n; int s, client_fd, clilen; fd_set read_fds; struct sockaddr_in client_addr, server_addr; if(argc != 2) { printf("Usage : %s port\n", argv[0]); exit(0); } if((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) { printf("Server: Can't open stream socket."); exit(0); } bzero((char *)&server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(atoi(argv[1])); if(bind(s,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0) { printf("Server: Can't bind local address.\n"); exit(0); } if (listen(s, 3) < 0) { printf("Server: Listen error.\n"); exit(0); } maxfdp1 = s + 1; while(1) { FD_ZERO(&read_fds); FD_SET(s, &read_fds); for(i=0; i<num_chat; i++) FD_SET(client_s[i], &read_fds); maxfdp1 = getmax(s) + 1; if (select(maxfdp1, &read_fds, (fd_set *)0, (fd_set *)0,(struct timeval *)0) < 0) { printf("select error <= 0 \n"); exit(0); } if(FD_ISSET(s, &read_fds)) { clilen = sizeof(client_addr); client_fd = accept(s, (struct sockaddr *)&client_addr, &clilen); if(client_fd == -1) { printf("accept error\n"); exit(0); } client_s[num_chat] = client_fd; num_chat++; send(client_fd, start, strlen(start), 0); printf("%d번째 사용자 추가.\n", num_chat); } for(i = 0; i < num_chat; i++) { if(FD_ISSET(client_s[i], &read_fds)) { if((n = recv(client_s[i], rline, MAXLINE, 0)) <= 0) { removeClient(i); continue; } if(strstr(rline, escapechar) != NULL) { removeClient(i); continue; } rline[n] = '\0'; for (j = 0; j < num_chat; j++) send(client_s[j], rline, n, 0); printf("%s\n", rline); } } } } void removeClient(int i) { close(client_s[i]); if(i != num_chat-1) client_s[i] = client_s[num_chat-1]; num_chat--; printf("채팅 참가자 1명 탈퇴. 현재 참가자 수 = %d\n", num_chat); } int getmax(int k) { int max = k; int r; for (r=0; r < num_chat; r++) { if (client_s[r] > max ) max = client_s[r]; } return max; }
select함수 부분쪽에서 전체적인 흐름을 잘 모르겠습니다.
몇 시간 째 뚫어져라 바라보고 이해해 볼라고 해도 중첩if나 for문
이 많아서 눈이 너무 햇갈립니다. 아직 select()함수에 대해 자세
히 이해를 못해서 그런걸가요?
특히 getmax()함수를 지워버리고 maxfdp1=getmax(s)+1
이부분을 maxfdp1=s+1이런식으로 사용해볼려고 했는데
getmax()함수 지우니까 아예 서버쪽에서 받고 보내기 자체가 않
되버리네요. getmax()정의한곳 보면 별거 없는거 같은데요 -.-
select() 함수부분쪽부터 이해할수 있게 주석좀 달아서 전체적인
흐름좀 이해할 수 있게 부탁드립니다.
Forums:
도움이 되실련지..
와우 섭다되서 잠시 들렸다가 ^^;;;
전 와우하러 히히
select()는 생각보다 사용하기가 꽤 어렵습니다. 먼저 getch()
select()는 생각보다 사용하기가 꽤 어렵습니다. 먼저 getch() 비슷한 함수를 select() 를 이용해서 한번 구현해보신 후에 위의 코드를 다시 보신다면 좀 더 잘 이해가 되지 않을까 싶군요.
차근차근 중간에 printf()함수를 집어넣어서 돌아가는 과정을 살펴보니
차근차근 중간에 printf()함수를 집어넣어서 돌아가는 과정을 살펴보니까
이제 좀 이해가 가네요^^;
근데 select()함수 가 사용되면 FD_SET() 에서 설정한 파일 지시자는
사라지는건가요? 정확히 어떤 부분에서 사라지는지 궁굼합니다.
그리고 첫번째 클라이언트에서 접속후 두번째 클라이언트가 접속하면
처음에 열린 소켓은 그대로 사용되고 accept()함수부분부터 바로 돌아가는
건가요? 나름대로 분석하다 보니까 그렇게 되는거 같은데 도움 부탁드립니다.
나에게 있어 한계란 없다.
무한한 꿈을향해 나아간다.
에~~ 우선, 다음 튜토리얼을 한번 읽으시길 권고 드립니다.htt
에~~ 우선, 다음 튜토리얼을 한번 읽으시길 권고 드립니다.
http://www.ecst.csuchico.edu/~beej/guide/net/
네트웍 프로그래밍에 있어서 그래도 가장 기초를 잘잡아주는 문서가 아닌가
하고요,
그리고, select 와 함께 사용해야할 매크로들(FD_SET 시리즈들..) 을 한번
알아보시길 바랍니다.
select() 같은 함수를 그냥 쉽게 배우려고 하면, 그런 절차를 수십번 겪어서,
결국은 select() 한번 고생한것과 같은량의 시간을 투자하셔야 합니다.
( 어쩌면 제대로 한번딱 고생하고, 잘 이해하는게 더 나을지도 모릅니다. )
삽질의 대마왕...
댓글 달기