TCP客户端套接字,不在select()上阻塞

TCP客户端套接字,不在select()上阻塞,c,select,tcpclient,C,Select,Tcpclient,以下代码是一个测试程序WRITEN,用于了解TCP客户端程序中select调用的行为。 我观察到的是select没有阻塞,而是程序在recv上阻塞。 结果如下: Wait on select. Wait on recv. ... 我的问题是为什么select返回成功?理想情况下,它应该在select而不是recv上阻塞。 TCP服务器每3秒钟发送一次15字节的字符串 int clientfd = -1; int dummyfd = -1; int maxfd = -1; struct sock

以下代码是一个测试程序WRITEN,用于了解TCP客户端程序中select调用的行为。 我观察到的是select没有阻塞,而是程序在recv上阻塞。 结果如下:

Wait on select.
Wait on recv.
...
我的问题是为什么select返回成功?理想情况下,它应该在select而不是recv上阻塞。 TCP服务器每3秒钟发送一次15字节的字符串

int clientfd = -1;
int dummyfd = -1;
int maxfd = -1;
struct sockaddr_in server_addr;

char recv_buf[100] = {0};
int msg_len = 0;
int bytes_recv = 0;
fd_set readfd;
int retval = 0;


/* Open the socket and a dummy socket */.
clientfd = socket(AF_INET, SOCK_STREAM, 0);
dummyfd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == clientfd || -1 == dummyfd)
{
    perror("socket error: ");
    exit(1);
}
printf("Socket opened : %d\n", clientfd);

server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(10000);
//server_addr.sin_addr.s_addr = INADDR_ANY;
inet_aton("127.0.0.1", &(server_addr.sin_addr));
memset(&(server_addr.sin_zero), 0, 8);

/* Connect to server */
if(connect(clientfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)))
{
    perror("connect error: ");
    exit(1);
}
printf("Connect Success\n");
maxfd = (clientfd > dummyfd) ? (clientfd + 1) : (dummyfd + 1);
while(1)
{
    FD_ZERO(&readfd);
    FD_SET(clientfd, &readfd);
    FD_SET(dummyfd, &readfd);
    printf("Wait on select\n");
    retval = select(maxfd , &readfd, NULL, NULL, NULL);
    if(retval <= 0)
    {
        printf("select failed\n");
    }
    else
    {
            printf("Wait on recv\n");
            /* ... The process waits here ... */
            bytes_recv = recv(clientfd, recv_buf, 100, 0);
            printf("%d: Bytes recv = %d\t%s\n", retval, bytes_recv, recv_buf);
            memset(recv_buf, 0 ,100);
    }
}

close(clientfd);
return 0;
}
编辑:如果没有dummyfd,程序将按预期工作。 后续问题: 当服务器突然关闭时,如何使用select检测此情况?
当服务器端崩溃时,是否可以修改程序,使其在select上阻塞?

使用以下命令以确保从select返回的是clientfd:


没有时间进行测试,但我怀疑dummyfd是作为EOF从select返回的,而不是clientfd。

使用以下命令以确保是clientfd从select返回:

retval = select(maxfd , &readfd, NULL, NULL, NULL);
if(retval <= 0)
{
    printf("select failed\n");
}
else
{
    if (FD_ISSET(clientfd, &readfd))
    {
        bytes_recv = recv(clientfd, recv_buf, 100, 0);
        ...
    }

    if (FD_ISSET(dummyfd, &readfd))
    {
        /* "dummyfd" processing */
    }

没有时间测试,但我怀疑dummyfd是作为EOF从select返回的,而不是从clientfd返回的。

select返回后,您将希望有条件地从clientfd接收。我猜dummyfd上可能有数据触发选择完成,但接收在clientfd上

retval = select(maxfd , &readfd, NULL, NULL, NULL);
if(retval <= 0)
{
    printf("select failed\n");
}
else
{
    if (FD_ISSET(clientfd, &readfd))
    {
        bytes_recv = recv(clientfd, recv_buf, 100, 0);
        ...
    }

    if (FD_ISSET(dummyfd, &readfd))
    {
        /* "dummyfd" processing */
    }

select返回后,您将希望有条件地从clientfd接收。我猜dummyfd上可能有数据触发选择完成,但接收在clientfd上

retval = select(maxfd , &readfd, NULL, NULL, NULL);
if(retval <= 0)
{
    printf("select failed\n");
}
else
{
    if (FD_ISSET(clientfd, &readfd))
    {
        bytes_recv = recv(clientfd, recv_buf, 100, 0);
        ...
    }

    if (FD_ISSET(dummyfd, &readfd))
    {
        /* "dummyfd" processing */
    }

我移除了dummyfd。正在等待选择。当服务器突然关闭时,会发生什么行为?现在,clientfd会返回EOF吗?是的,当select返回时,您应该始终检查EOF,如果是,请从您的select列表中删除该fd。我删除了dummyfd。正在等待选择。当服务器突然关闭时,会发生什么行为?现在,clientfd是否会返回EOF?是的,当select返回时,您应该始终检查EOF,如果是,请从select列表中删除该fd。