【问题标题】:TCP client socket, doesn't block on select()TCP 客户端套接字,不会阻塞 select()
【发布时间】:2011-06-09 20:59:23
【问题描述】:


以下代码是为了解 TCP 客户端程序中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() 上阻塞吗?

【问题讨论】:

    标签: c select tcpclient


    【解决方案1】:

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

    else if (FD_ISSET(clientfd, &readfd)) {
    

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

    【讨论】:

    • 我删除了 dummyfd。现在等待选择。
    • 服务器突然关闭是什么行为?现在,clientfd 会返回 EOF 吗?
    • 是的,您应始终检查选择返回时的EOF,如果是,则从选择列表中删除该FD。
    【解决方案2】:

    在 select() 返回后,您将希望有条件地从 clientfd 接收。我的猜测是 dummyfd 上可能有数据触发 select 完成,但接收在 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 */
        }
    

    【讨论】:

      猜你喜欢
      • 2017-04-18
      • 2017-01-29
      • 1970-01-01
      • 2016-03-18
      • 2012-10-13
      • 1970-01-01
      • 2020-10-30
      • 1970-01-01
      • 2012-03-29
      相关资源
      最近更新 更多