背景

我的服务器是两段式访问确认机制,第二次等候客户端衔接的accept操作会一向堵塞,直到衔接呈现或出错停止。但是我不希望它因为客户端呈现某些不明问题而一向挡在那里,所以希望设置堵塞时刻来主动开释资源。

思路

根据网上的计划,推荐用select函数来设置超时。
这个函数是经过查看缓冲区是否有数据来判断客户端衔接是否到来。
如果咱们在确定了客户端衔接现已到来之后再履行accept来接受客户端恳求的话,就避免了堵塞。

实践

根据网上的代码演示,大致为以下写法:

struct fd_set rdfs;

while(1){
    struct timeval  tv = {5 , 0};   // 设置5秒时刻
    FD_ZERO(&rdfs);
    FD_SET(sockfd, &rdfs);
    if (select(sockfd+1, &rdfs, NULL, NULL, &tv) > 0)   // socket就绪
    {
          recv() /  recvfrom()    //  从socket读取数据
    }
}

以上代码转自:http://www.dtmao.cc/java/76933.html

实测无效。

根据测验发现,该办法设置的超时很奇怪,不管我是否主动让客户端衔接延迟回复,select都会堵塞设定的时刻(5s),有点像是在select函数中加了个sleep(5s)。这显然不是我想要的。

不过经过测验发现select函数仍是能够正确检测到当客户端恳求到来后缓冲区变化的。所以能够经过自己设置超时计时,合作select检测的方式完成真实的超时检测。

终究完成

代码如下:

    time_t time = getCurTick();
    while (1) {
        struct fd_set rdfs;
        struct timeval  tv = { 0 , 0 };   // 设置0秒时刻,使得select函数本身不会堵塞等候
        FD_ZERO(&rdfs);
        FD_SET(inNode->MySocket, &rdfs);
        if (select(inNode->MySocket + 1, &rdfs, NULL, NULL, &tv) > 0)   // socket就绪查看
        {
            cSocket = accept(inNode->MySocket, (struct socketaddr*)&c_addr, 0);//查看到了客户端恳求,接纳恳求后退出。
            break;
        }
        if (getCurTick() - time > 5 && time > 0) //查看当时时刻间隔开端计时的时刻是否超过5s
        {
            //超时整理资源,退出
            printf("client timeout 5s\n");
            closesocket(inNode->MySocket);
            ListRemoveNode(LIST_CONNECT_TCP, inNode);
            return -4;
        }
    }

注:
struct fd_set rdfs;
struct timeval tv = { 0 , 0 };
FD_ZERO(&rdfs);
FD_SET(inNode->MySocket, &rdfs);

这些必须设置,比如如果设置为NULL的话select检测会无效。