EAGAIN의 이유?
글쓴이: urmajest / 작성시간: 월, 2005/04/25 - 3:38오후
안녕하세요.
간단한 서버/클라이언트 프로그램을 구현하고 있습니다.
그런데 이상한 현상이 일어나네요.
서버에서는 TCP connection을 기다리면서,
키보드 입력이 있으면 바로 종료하도록 하는데요.
// 커넥션 정보를 쓰레드에 넘겨주기 위한 구조체 struct connection { sockaddr_in addr; int connfd; } int Server::ready() { int listenfd, val, maxfd; socklen_t length; pthread_t tid; sockaddr_in servAddr; connection* c; fd_set rset, wset; cout << "<READY> (press enter key to exit)\n"; bzero(&servAddr, sizeof(servAddr)); servAddr.sin_family = AF_INET; servAddr.sin_addr.s_addr = htonl(INADDR_ANY); servAddr.sin_port = htons(SERV_PORT); if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("Socket error"); return 1; } // Set the both STDIN and listenfd NONBLOCKING val = fcntl(listenfd, F_GETFL, 0); fcntl(listenfd, F_SETFL, val | O_NONBLOCK); val = fcntl(STDIN_FILENO, F_GETFL, 0); fcntl(STDIN_FILENO, F_SETFL, val | O_NONBLOCK); if (listenfd > STDIN_FILENO) maxfd = listenfd + 1; else maxfd = STDIN_FILENO + 1; if (bind(listenfd, (struct sockaddr*)&servAddr, sizeof(servAddr)) < 0) { perror("Bind error"); return 1; } if (listen(listenfd, LISTENQ) < 0) { perror("Listen error"); return 1; : } for (;;) { FD_ZERO(&rset); FD_ZERO(&wset); FD_SET(STDIN_FILENO, &rset); FD_SET(listenfd, &rset); select(maxfd, &rset, &wset, NULL, NULL); if (FD_ISSET(STDIN_FILENO, &rset)) { char buf[BUFSIZE]; // empty stdin read(STDIN_FILENO, buf, BUFSIZE); // set back to BLOCKING val = fcntl(STDIN_FILENO, F_GETFL, 0); fcntl(STDIN_FILENO, F_SETFL, val ^ O_NONBLOCK); break; } c = (connection*) malloc(sizeof(connection)); length = sizeof(c->addr); if ( (c->connfd = accept(listenfd, (struct sockaddr*) &(c->addr), &length)) < 0) { perror("Accept error"); break; } // set back to BLOCKING val = fcntl(c->connfd, F_GETFL, 0); fcntl(c->connfd, F_SETFL, val ^ O_NONBLOCK); c->s = this; // create a thread to serv pthread_create(&tid, NULL, &serv, c); } close(listenfd); return 0; } static void* serv(void* arg) { int connfd, verbose, n, h_errnop; Server* s; struct sockaddr_in cliAddr; msg msgbuf; connfd = ((connection*) arg)->connfd; cliAddr = ((connection*) arg)->addr; s = ((connection*) arg)->s; verbose = s->verbose; free(arg); // detach pthread_detach(pthread_self()); // read the request if ((n = read(connfd, &msgbuf, sizeof(msgbuf))) < 0) /*** 바로 여기!! ***/ perror("read"); else { int type, subtype, variable, subscript; type = ntohl(msgbuf.type); subtype = ntohl(msgbuf.subtype); variable = ntohl(msgbuf.variable); subscript = ntohl(msgbuf.subscript); // is hello? if (type == T_REQUEST && subtype == ST_HELLO) { //struct hostent* host;
이런 식으로 되어 있습니다.
그런데 잘 동작하다가 가끔 소스중에 "바로 여기!" 라고 적은
read가 EAGAIN을 errno로 발생시키네요.
select에서 넘어왔다면 분명히 소켓버퍼에 데이터가 있을 터인데,
EAGAIN을 뱉네요. 도와주세요~~
Forums:
[code:1] val ^ O_NONBLOCK ==> val &am
val ^ O_NONBLOCK ==> val & ~O_NONBLOCK
이렇게 해야 할 것 같은데요...
댓글 달기