当tcp处于关闭等待状态时,选择始终返回1

当tcp处于关闭等待状态时,选择始终返回1,c,linux,sockets,tcp,C,Linux,Sockets,Tcp,我写了一个服务器/客户端程序。然后使用选择检查插座。但当客户端关闭套接字(服务器中的tcp状态将进入close\u wait)时,选择always return 1,errno为0 为什么选择返回1?Tcp套接字现在没有要读取的内容 服务器: int sock = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(IN

我写了一个服务器/客户端程序。然后使用
选择
检查插座。但当客户端关闭套接字(服务器中的tcp状态将进入
close\u wait
)时,选择always return 1,errno为0

为什么选择返回1?Tcp套接字现在没有要读取的内容

服务器:

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));
}
输出:

./server 
ret:1, Success
ret:1, Success
ret:1, Success

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

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

由于select可以同时监视多个文件描述符,并且每个文件描述符使用一个位,因此无法区分“数据已到达”和“另一端的套接字已关闭”。这两个事件都将套接字标记为“可读”


在监视写入时也是如此。如果另一方关闭其端点,则套接字将被标记为“可写”,这与select有关。在实际尝试写入套接字之前,不会出现错误。

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

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

由于select可以同时监视多个文件描述符,并且每个文件描述符使用一个位,因此无法区分“数据已到达”和“另一端的套接字已关闭”。这两个事件都将套接字标记为“可读”


在监视写入时也是如此。如果另一方关闭其端点,则套接字将被标记为“可写”,这与select有关。在实际尝试写入套接字之前,不会出现错误。

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

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

由于select可以同时监视多个文件描述符,并且每个文件描述符使用一个位,因此无法区分“数据已到达”和“另一端的套接字已关闭”。这两个事件都将套接字标记为“可读”


在监视写入时也是如此。如果另一方关闭其端点,则套接字将被标记为“可写”,这与select有关。在实际尝试写入套接字之前,不会出现错误。

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

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

由于select可以同时监视多个文件描述符,并且每个文件描述符使用一个位,因此无法区分“数据已到达”和“另一端的套接字已关闭”。这两个事件都将套接字标记为“可读”


在监视写入时也是如此。如果另一方关闭其端点,则套接字将被标记为“可写”,这与select有关。在您真正尝试写入套接字之前,您不会得到错误。

套接字是可读的,因为对等方已关闭它,当您从中读取时,您将得到流的结束。而不是什么都没有


CLOSE_WAIT表示TCP正在等待您关闭套接字。所以关闭它。

套接字是可读的,因为对等方已经关闭了它,当您从中读取时,您将获得流的结束。而不是什么都没有

CLOSE_WAIT表示TCP正在等待您关闭套接字。关上它。

袜子
./server 
ret:1, Success
ret:1, Success
ret:1, Success