【发布时间】:2014-09-05 18:54:39
【问题描述】:
我写了一个服务器/客户端程序。并使用select 检查套接字。但是当客户端关闭套接字时(服务器中的tcp状态将进入close_wait),选择总是返回1并且errno为0。
为什么select 返回 1? Tcp socket 现在没有什么可读的了!
服务器:
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(6999);
socklen_t socklen = sizeof(struct sockaddr_in);
bind(sock, (struct sockaddr *)&addr, socklen);
listen(sock, 0);
int clisock;
clisock = accept(sock, NULL, NULL);
fd_set backset, rcvset;
struct timeval timeout;
timeout.tv_sec = 3;
int maxfd = clisock+1;
FD_SET(clisock, &rcvset);
backset = rcvset;
int ret;
while(1) {
rcvset = backset;
timeout.tv_sec = 3;
ret = select(maxfd, &rcvset, NULL, NULL, &timeout);
if(ret <= 0)
continue;
sleep(1);
printf("ret:%d, %s\n",
ret, strerror(errno));
}
客户:
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(6999);
socklen_t socklen = sizeof(struct sockaddr_in);
connect(sock, (struct sockaddr *)&addr, socklen);
sleep(3);
close(sock);
sleep(100);
输出:
./server
ret:1, Success
ret:1, Success
ret:1, Success
【问题讨论】:
-
当远程端点关闭其连接时,本地端点将变得可读,但
read返回0。那表示远程端点已经关闭,read返回0。 -
关于你对
errno的使用,除非确实有是错误,否则不要检查它,并且总是在错误的函数调用之后直接检查它(即如果@987654332 @失败你必须在select之后直接检查errno)。想想如果sleep失败会发生什么?然后errno将包含来自sleep函数的错误。 -
你已经告诉 select() 当你可以从套接字读取时你想要一个通知。您应该从套接字读取,然后您可以检查从套接字读取是否在该套接字上给您一个错误。 (select() 可以监视许多套接字,当您监视套接字的读取事件时,select() 不会指示某个特定套接字上的错误)。如果您在 select() 告诉您可以读取时选择不从套接字读取,则 select() 会告诉您在下一次迭代中您仍然可以从它读取。
-
最后,记住
select修改集合,所以如果你在传递给select的集合中有多个描述符,你必须清除集合并再次添加所有描述符。 -
errno的值如果没有错误是未定义的,除非有错误,否则不要检查。