【问题标题】:Check socket with select() before using send()在使用 send() 之前使用 select() 检查套接字
【发布时间】:2017-04-21 22:32:16
【问题描述】:

我正在使用我的客户端写入服务器。我想检查套接字是否已打开以在我的客户端中写入,如果在建立连接后 10 秒内它还没有准备好,那么我想打印一条错误消息并由于超时而退出我的客户端。

客户端仅使用发送功能即可正常工作,并且我能够将文件从客户端传输到服务器。但是,当我实现 select() 功能时,客户端现在将超时,将 sel_value 设置为 0。

为了更容易阅读,我删除了执行发送功能的代码,因为有一些额外的逻辑可以将内容读入缓冲区。

//set up select for sending
fd_set wfds;
struct timeval timeout;
while (1) {
    FD_ZERO(&wfds);
    FD_SET(sockfd, &wfds);

    timeout.tv_sec = 10;
    timeout.tv_usec = 0; //no us

    int sel_value = select(sockfd+1, &wfds, NULL, NULL, &timeout);
    cout<<"sel_value is: "<<sel_value<<endl;
    if(sel_value == -1){
        perror("select");

    }else if(sel_value == 0){
        printf("Timeout. Cannot send for 10s \n");
        break;
    }
    else{
        if(FD_ISSET(sockfd, &wfds)){
            //my code never reaches this point, but here is where we send
            //code to send stuff
        }
    }

}

【问题讨论】:

标签: c++ sockets select


【解决方案1】:

你是从头到尾这样做的。您应该只进行发送,并且仅在发送导致 EAGAIN/EWOULDBLOCK 时才选择可写性。套接字几乎总是准备好写入,除非套接字发送缓冲区已满。以您的方式将系统调用加倍并增加延迟。

【讨论】:

  • 我有点困惑。如果我发送,那么我需要检查是否 errno=EAGAIN || errno = EWOULDBLOCK。如果 errno 是这些值之一,我是否尝试重新发送?一种方法是调用 select() 然后读取它的返回值:如果它准备好写入,那么我可以执行 continue() 然后返回循环中的发送?
  • 我已经回答过了。如果errno 是 EAGAIN/EWOULDBLOCK,则选择。
  • 即使我的套接字阻塞,你所说的也能正常工作吗?
  • 不。不适用于阻塞。我使套接字无阻塞,一切都很好。谢谢!
  • 如果套接字阻塞,它将阻塞而不是导致 EAGAIN/EWOULDBLOCK。
【解决方案2】:

用于写入设置第三个字段,即:

select(sockfd+1, NULL, &wfds, NULL, &timeout);

【讨论】:

    猜你喜欢
    • 2014-08-11
    • 2021-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-22
    • 2019-05-30
    • 2017-07-23
    相关资源
    最近更新 更多