둘 이상이 접속하면 select에서 에러가 납니다.
글쓴이: wizmusa / 작성시간: 목, 2003/04/10 - 1:10오전
안녕하세요? 처음으로 질문을 올립니다.
핸드폰으로 접속하여 그림을 다운받는 프로그램을 짜고 있습니다. 그런데 둘 이상이 접속을 하면 select에서 에러가 나버립니다. 물론 혼자 접속하면 종료되지 않고 몇 번을 접속해서 다운을 받아도 잘 됩니다. (-_-) 넷에서 돌아다니는 채팅 서버 소스를 고쳐서 만들고 있는데요... 뭐가 문제인지 잘 모르겠습니다. 그저 select에서 에러가 난다는 것만을 알 뿐입니다. 어떻게 해야 에러가 없어질까요?
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; // int threadFd ; int ret; BYTE readline[SBUF_LEN]; int length, len ; int addrLen; uint magic, block ; int mode, imageKey ; pthread_t thread_id ; // fd_set read_fds; /* 읽기를 감지할 소켓번호 구조체 */ struct sockaddr_in client_addr, server_addr; if(argc != 2) { printf("사용법 :%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); } // umask(0); setDemon(); if ( fork() ) { exit(0); } setpgrp(); // /* server_addr 구조체의 내용 세팅 */ 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); } /* 클라이언트로부터 연결요청을 기다림 */ listen(s, 50); // 원랜 5였습니다. maxfdp1 = s + 1; /* 최대 소켓번호 +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; /* maxfdp1 재 계산 */ if (select(maxfdp1, &read_fds, (fd_set *)0, (fd_set *)0,(struct timeval *)0) < 0) { //if (select(maxfdp1, &read_fds, (fd_set *)0, (fd_set *)0,NULL) < 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)) { threadFd = client_s[i]; memset( &thread_id, 0, sizeof(thread_id) ); if(pthread_create(&thread_id, NULL, (void *)doDownLoad, (void *)&threadFd)) /* doDownLoad는 쓰레드로 실행시킵니다.(?) 실제로 서버에서 다운받는 부분입니다. 혹시 쓰레드를 만들기 때문에 셀렉트에서 에러가 날까요?*/ { logDebug("dlServer startServer(), FAIL_CREATE_THREAD, errno = %d \n", errno); } } } } }
혹시 쓰레드를 잘못 쓰면 select에서 착오를 일으키는걸까요?
아니면 select 이전에 제가 뭔가를 잘못 썼기 때문일까요?
답변 부탁드립니다.
Forums:
일단 오류의 내용을 보세요.[code:1] if (
일단 오류의 내용을 보세요.
우리 모두 리얼리스트가 되자. 그러나 가슴에 이룰 수 없는 꿈을 가지자
stoneshim님께서 말씀해주신대로 해봤습니다.
select: Bad file descriptor 라는 메시지가 나오면서 종료됩니다.
세 개의 클라이언트끼리 서로 싸워가면서(?) - 계속 재접속시도를 하면서 이미지를 다운로드받다가는 위의 메시지가 나오면서 종료되었습니다.
평화가 함께 하기를...
추축입니다만.. maxfdp1 값이 잘못되서 그런것이 아닐까요??
추축입니다만.. maxfdp1 값이 잘못되서 그런것이 아닐까요??
client가 접속하면.. client sock fd 값은 s값 보다 클수 있는데..
maxfdp1값은 s에서 최대 값을 찾고 있으니....
getmax()라는 함수에서 어떻게 처리해주는지 모르겠내요..
maxfdp1쪽을 확인보시는 것도 좋을듯 하내요..
그럼..
이 부분이 문제입니다.[code:1] /* 채팅 클
이 부분이 문제입니다.
다음과 같이 처리해 주셔야 합니다.
우리 모두 리얼리스트가 되자. 그러나 가슴에 이룰 수 없는 꿈을 가지자
최대값 찾기...
maxfdp1 = getmax(s) + 1; /* maxfdp1 재 계산 */
일단 s 중에서 최대값을 찾고 거기에 1을 더하는 것으로 했는데요...
getmax()는 다음과 같습니다.
원래 소스에 있었던 것인데 그냥
maxfdp1 = s + 1;
로 해봤더니 다운로드가 실행되지않더라구요...
평화가 함께 하기를...
stoneshim님 말씀대로 해봤습니다.
stoneshim님 말씀대로 해봤습니다. 이제는 동시 접속이 일어났다고 해서 서버프로그램이 종료되지는 않습니다. 그런데 아무래도 원래 주신대로 하면 에러가 나서요... 제가 우선 다음과 같이 바꿔서 했습니다.
아무래도 좀 이상하게 고쳤지만 일단 돌려봤습니다. :?
그랬더니 앞서 말씀드린대로 서버프로그램이 종료되지는 않는데 첫번째 접속자도 63번째(MAX_SOCK이 63입니다.)로 나오면서 클라이언트들이 접속만 하고 다운로드를 진행하지 않습니다. 재접속을 시키면 받기는 합니다만 제대로 돌아가는 건 아니겠지요. 일단 다른 방식으로 다시 시도해보겠습니다만 어렵네요. 시간도 별로 없는데... :cry:
평화가 함께 하기를...
제가 코딩 중에 잘못된 부분이 있었군요.[code:1]
제가 코딩 중에 잘못된 부분이 있었군요.
말씀하신 현상은 초기화를 안해주신것 같습니다.
우리 모두 리얼리스트가 되자. 그러나 가슴에 이룰 수 없는 꿈을 가지자
여전히 에러가 납니다.
초기화는 해주었는데요... 아무래도
여기에서 client_s[i]에 무조건 client_fd 값이 들어가는 것 같습니다. 그러니까 num_chat에는 무조건 최대값 63이 들어가게 되구요... 여러 클라이언트가 접속하면 select: Bad file descriptor 에러도 여전히 발생하구요... 어떻게 된건지 도무지 모르겠네요...
평화가 함께 하기를...
[code:1] /* 채팅 클라이언트 목록에 추가 */
죄송합니다. 대충 로직만 말씀드린다는 생각으로... 정확한 코딩이 아니었습니다.
우리 모두 리얼리스트가 되자. 그러나 가슴에 이룰 수 없는 꿈을 가지자
댓글 달기