背景
我的服务器是两段式访问确认机制,第二次等候客户端衔接的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检测会无效。