[급질문] 아주 돌아버리겠습니다.
글쓴이: leolo / 작성시간: 월, 2005/03/28 - 1:42오후
제가 UDP 서버를 하나 돌리고 있습니다.
이 서버에는 최대 삼천개 정도의 클라이언트가 붙습니다.
하지만, 아래 상황은 약 30개만 붙어도 이런 경우가 생겼습니다.
UDP 서버의 프로그램 구성은 이렇습니다.
스레드1 : 서버가 클라이언트로 부터 데이터를 받으면, queue에 바로 넣습니다.
스레드2 : queue 정보를 pop하고 가공하여 DB에 클라이언트의 IP와 기타 정보를 insert합니다.
스레드3 : 다른 내부 프로세스로 부터 정보를 받아 DB의 클라이언트의 IP로 관련 정보를 보냅니다.
간단히 설명 드리면 이러한 구조입니다.
문제는 어느 순간 클라이언트가 접속하면 접속이 안됩니다.
문제는 보시면 제 UDP 서버가 9097 포트를 열고 있는데요.
netstate -l 해서 보시면,
udp 261856 0 localhost:10008 *:*
라인처럼 Recv-Q 가 full이 되어버립니다. 왜. 이렇게 되는지 모르겠습니다.
저는 recvfrom해서 데이터 얻고, 바로 queue에 넣기 때문에 문제 없을 것으로 판단이 되는데요.
또한, 제 서버는 9097 포트로 데이터를 받는데요. 프로세스를 실행시키면, *:9097 뿐만 아니라, localhost:10008 도 같이 나타나는데.. 이건 무슨 의미인지요?
좀 두서 없더라고 답변 꼭 부탁드립니다...
[ering@localhost ering]$ netstat -l Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 localhost:32768 *:* LISTEN tcp 0 0 *:2244 *:* LISTEN tcp 0 0 localhost:8005 *:* LISTEN tcp 0 0 *:8009 *:* LISTEN tcp 0 0 *:mysql *:* LISTEN tcp 0 0 *:sunrpc *:* LISTEN tcp 0 0 *:webcache *:* LISTEN tcp 0 0 *:http *:* LISTEN tcp 0 0 *:ftp *:* LISTEN tcp 0 0 *:ssh *:* LISTEN tcp 0 0 *:telnet *:* LISTEN udp 0 0 *:9097 *:* udp 0 0 localhost:10001 *:* udp 0 0 localhost:10002 *:* udp 0 0 localhost:10003 *:* udp 0 0 localhost:10004 *:* udp 0 0 localhost:10005 *:* udp 0 0 localhost:10006 *:* udp 0 0 localhost:10007 *:* udp 261856 0 localhost:10008 *:* udp 0 0 localhost:10009 *:* udp 0 0 *:sunrpc *:* Active UNIX domain sockets (only servers)
Forums:


9097 은 현재 UDP 로 서버로서 대기하고 있는 포트이구요나머지는
9097 은 현재 UDP 로 서버로서 대기하고 있는 포트이구요
나머지는 클라이언트들이 붙으면서 순간적으로 열리는 포트일껍니다.
제 생각엔 코드조각을 좀 보여주셔야 단서를 잡겠네요
^^ be cool ~
http://fromdj.pe.kr
첫번째 쓰레드 queue에 넣는 부분..[code:1]
첫번째 쓰레드 queue에 넣는 부분..
while(is_running) { FD_ZERO(&read_fd); FD_SET(sock, &read_fd); maxfd = MAX(maxfd, sock); memset(recvBuf, 0x00, sizeof(recvBuf)); result = select(maxfd + 1, &read_fd, NULL, NULL, NULL); if(result < 0) { if(errno != EINTR) { } continue; } if(FD_ISSET(sock, &read_fd)) { if((rc = recvfrom(sock, recvBuf, sizeof(recvBuf), 0, (struct sockaddr *)&svr_host.adr, &si)) < 0) { } memset(&smessage, 0x00, sizeof(smessage)); memcpy(&smessage, recvBuf, sizeof(smessage)); qs = queue_push(g_recv_queue, &smessage, sizeof(smessage)); if(qs != QUEUE_SUCCESS) { .....큐에 들어간 메시지를 팝해서 처리함.
while(is_running) { r = queue_pop(g_recv_queue, buf, 1); if(r == QUEUE_EMPTY) continue; msg = (msghd *)buf; switch(ntohl(msg->type)) { case REQ_CLI_LOGIN : memset(query, 0x00, sizeof(query)); sprintf(query, "INSERT INTO MESS_CLIENT_INFO (PHONE, IP, FORWARD) VALUES('%s', '%s', %d)", login_req->phone, inet_ntoa(svr_host.adr.sin_addr), ntohl(login_req->forward)); if((ret = insert_mysql(query)) == K_SUCCESS) send_login_res(svr_host.sock, ntohl(login_req->idx), 0x01); // LOGIN 성공. .................다른 프로세스에서 데이터 받아 클라이언트로 전송함.
while(is_running) { memset(packet, 0x00, sizeof(packet)); rc = comm_recv(m_mess_transport, packet, sizeof(packet), 1000); if(rc <= 0) { if(rc != EPE_TIMEOUT) { continue; } } else { pheader = (pointheader *)packet; switch(ntohl(pheader->msgid)) { case REQ_MESS_ANI_INFO : { ANI_INFO_REQ *ani_req = (ANI_INFO_REQ *)packet; if(svr_host.sock > 0) // 서버 socket이 살아있음. { .... 클라이언트에게 메세지 보냄..실력이 있으면 삶이 편하다... 영차 영차...
현재 고려한 부분은 굳이 UDP이니까. select 없이, 그냥..re
현재 고려한 부분은 굳이 UDP이니까. select 없이, 그냥..recvfrom 만 사용해서 blocking 모델로 수정하고 있습니다.
실력이 있으면 삶이 편하다... 영차 영차...
[quote="zoocmic"]9097 은 현재 UDP 로 서버로서 대기
그런데요. UDP 서버 프로그램을 수행하면 바로 localhost:10008 가 나옵니다. 죽이면 없어지고요.. 물론 9097 라인도 마찬가지 입니다.
[ering@localhost mess]$ netstat -l
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 *:32768 *:* LISTEN
tcp 0 0 localhost:32769 *:* LISTEN
tcp 0 0 *:2244 *:* LISTEN
tcp 0 0 localhost:8005 *:* LISTEN
tcp 0 0 *:8009 *:* LISTEN
tcp 0 0 *:mysql *:* LISTEN
tcp 0 0 *:sunrpc *:* LISTEN
tcp 0 0 *:webcache *:* LISTEN
tcp 0 0 *:http *:* LISTEN
tcp 0 0 *:ftp *:* LISTEN
tcp 0 0 *:ssh *:* LISTEN
tcp 0 0 localhost:ipp *:* LISTEN
tcp 0 0 *:telnet *:* LISTEN
tcp 0 0 localhost:smtp *:* LISTEN
udp 0 0 *:32768 *:*
udp 0 0 *:9097 *:*
udp 0 0 localhost:10008 *:*
udp 0 0 *:sunrpc *:*
udp 0 0 *:758 *:*
udp 0 0 *:631 *:*
실력이 있으면 삶이 편하다... 영차 영차...
잘 알지는 못하지만... maxfd의 값을 한번 printf를 이용해서
잘 알지는 못하지만... maxfd의 값을 한번 printf를 이용해서 찍어보세요.
그것과 관련있을듯 한데...
FD_ISSET이후에 accept를 한후에 그 소켓값을 close해야 다른 client가 사용할
포트가 생깁니다.(잘 아시겠지만요...)
알아서 소켓을 닫아주는건 프로그램이 끝날때 하는일이고(물론 그 이후 얼마까지는
해당 포트에 접근하지도 못하지만요...)
혹시 30여개의 client만 붙고나면 다른 client가 붙지 않는 이유가 close를 지정하지
않아서 일까해서 적어봤습니다.
(근거는
http://www.cis.ksu.edu/~singh/CIS725/Fall99/programs/sock_ipc_tut.html
tut7.c정도가 될듯하네요. :oops: )
------------------------------
좋은 하루 되세요.
댓글 달기