0

嗨,我正在创建一个代理服务器,它通过 UDP 连接等待来自客户端的数据包,并检查它们是否都有效到达或是否相同。

在这种情况下,我应该为每个丢失的数据包(使用 send_ack() )向客户端发送一个“ack”,但是在发送第一个 ack 之后,选择循环的“if 部分”发送无限的 ack 永远不会回到“else”部分”是来自客户端的选择监听数据(接收 _pkt() 函数)

fd_set rset, allset;
int maxfd, nready;
struct timeval timeout;

timeout.tv_sec = 4;
timeout.tv_usec = 150000; 
maxfd = socketfd;  
FD_ZERO(&allset);
FD_SET(socketfd, &allset);
rset = allset;

for( i=0; ;i++){
    do {
        nready=select( (maxfd +1), &rset, NULL, NULL,  &timeout); 
    } while ((nready<0) & (errno==EINTR)); 

    if( nready<0) {
        perror("Error main: select failed: ");
        exit(32);
    }  
    if( nready==0){ 
        send_ack(socketfd,head);
    }
    else{           
        receive_pkt(socketfd, head);
    }
}

希望它足够清楚,感谢您的建议!

4

2 回答 2

2

在某些系统(特别是 Linux)上,select调用会修改超时以显示还剩多少时间。因此,在您的情况下,如果它等待一个数据包 3 秒,超时将减少到 1.15 秒,总共 4.15 秒后,超时将为 0,因此稍后调用select将立即返回 nready == 0。

如果您想在发送 ack 后再次等待,则需要将超时重置为非零。

于 2013-03-18T16:14:52.730 回答
2

fd_set rset必须在每次调用之前重置select. 该select调用需要一组字段描述符来监视并用一组字段描述符覆盖,并带有要读取的通知。

for( i=0; ;i++){
    do {
        rset = allset;
        nready=select( (maxfd +1), &rset, NULL, NULL,  &timeout); 
    } while ((nready<0) & (errno==EINTR)); 
于 2013-03-18T16:18:54.807 回答