UDP套接字使用select()

时间:2013-03-18 15:30:21

标签: c sockets multiplexing

您好我正在创建一个代理服务器,它等待来自具有UDP连接的客户端的数据包,并检查所有这些数据包是否已经有效到达或者是否已被拒绝。

在这种情况下,我应该为每个丢失的数据包(使用send_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);
    }
}

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

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:2)

必须在每次调用fd_set rset之前重置selectselect调用需要一组字段描述符来监视和覆盖一组字段描述符以及要读取的通知。

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