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이렇게 해야 할 것 같은데요...
댓글 달기