当tcp在close_wait时,select总是返回1

时间:2014-09-03 08:18:53

标签: c linux sockets tcp

我写了一个服务器/客户端程序。并使用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

2 个答案:

答案 0 :(得分:2)

套接字是可读的,因为对等体已关闭它,当您从中读取时,您将获得流的结束。而不是一无所获。

CLOSE_WAIT表示TCP正在等待关闭套接字。如此接近它。

答案 1 :(得分:1)

选择返回,因为它监视的其中一个套接字上有一个事件。该文档使用术语&#34;可读&#34;。在这个cas中它有点误导,因为另一端的套接字是关闭的,并且没有字节可以从中读取。文档的措辞是因为select适用于任何类型的文件描述符。 &#34;文件&#34;可以是套接字,管道或普通文件。他们不想被不同类型的文件描述符的细节纠缠在一起。

另一端的套接字关闭是正常的,因此在这种情况下select不应该返回错误。当您尝试从套接字中实际读取时,一旦读取了所有可用数据,如果连接已在另一端关闭,则会出现错误。

由于select可以一次监视多个文件描述符,并且对每个文件描述符使用一个位,因此无法区分&#34;数据已到达&#34; &#34;另一端的插座已关闭&#34;。这两个事件都会将套接字标记为&#34;可读&#34;。

监控写作时也是如此。如果另一方关闭其端点,则套接字将被标记为&#34;可写&#34;就选择而言。在你真正尝试写入套接字之前,你不会得到错误。