我写了一个服务器/客户端程序。并使用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
答案 0 :(得分:2)
套接字是可读的,因为对等体已关闭它,当您从中读取时,您将获得流的结束。而不是一无所获。
CLOSE_WAIT表示TCP正在等待你关闭套接字。如此接近它。
答案 1 :(得分:1)
选择返回,因为它监视的其中一个套接字上有一个事件。该文档使用术语&#34;可读&#34;。在这个cas中它有点误导,因为另一端的套接字是关闭的,并且没有字节可以从中读取。文档的措辞是因为select适用于任何类型的文件描述符。 &#34;文件&#34;可以是套接字,管道或普通文件。他们不想被不同类型的文件描述符的细节纠缠在一起。
另一端的套接字关闭是正常的,因此在这种情况下select不应该返回错误。当您尝试从套接字中实际读取时,一旦读取了所有可用数据,如果连接已在另一端关闭,则会出现错误。
由于select可以一次监视多个文件描述符,并且对每个文件描述符使用一个位,因此无法区分&#34;数据已到达&#34; &#34;另一端的插座已关闭&#34;。这两个事件都会将套接字标记为&#34;可读&#34;。
监控写作时也是如此。如果另一方关闭其端点,则套接字将被标记为&#34;可写&#34;就选择而言。在你真正尝试写入套接字之前,你不会得到错误。