最近开发设备控制程序的过程中遇到一个问题,由于流程控制需要,必须使用阻塞的TCP套接字,正常使用没有什么问题,但是如果目标IP不存在,或者无效,则connect的等待时间很长,测试大概为20S左右,这个响应时间是无法容忍的,因此必须进行优化,开始考虑Ping这个地址,如果主机有回应,再去连接,否则就不进行连接,但是考虑到防火墙的原因,这个未必能达到我们的要求,BAIDU了一下,发现了一个好办法,就是用select去阻塞,等待套接字可写,这个超时时间是我们可以设置的。具体做法是先设置套接字为非阻塞的套接字,然后select去等待套接字可写,然后再将套接字设为非阻塞的。
具体做法见代码:
//设置非阻塞方式连接
unsigned long ul = 1;
int iRet = ioctlsocket(hSocket, FIONBIO, (unsigned long*)&ul);
if(iRet == SOCKET_ERROR)
{
ATLTRACE("设置非阻塞套接字失败deviceInd = %d\n", deviceInd); ;
}
ZeroMemory(&svrsockaddr, sizeof sockaddr_in);
svrsockaddr.sin_family = AF_INET;
svrsockaddr.sin_addr.S_un.S_addr = htonl(dwAddr);
svrsockaddr.sin_port = htons(nTxPort);
iRet = connect(hSocket,(sockaddr*)(&svrsockaddr),sizeof(svrsockaddr));
//select 模型,即设置超时
struct timeval timeout;
fd_set r;
FD_ZERO(&r);
FD_SET(hSocket, &r);
timeout.tv_sec = 3; //连接超时3秒
timeout.tv_usec =0;
iRet = select(0, 0, &r, 0, &timeout);
if ( iRet <= 0)
{
m_bIsConnectDevice[deviceInd] = false;
ATLTRACE("等待连接超时失败deviceInd = %d\n", deviceInd);
}
else
{
//一般非锁定模式套接比较难控制,可以根据实际情况考虑 再设回阻塞模式
unsigned long ul1= 0;
iRet = ioctlsocket(hSocket, FIONBIO, (unsigned long*)&ul1);
if(iRet == SOCKET_ERROR)
{
ATLTRACE("设置阻塞套接字失败deviceInd = %d\n", deviceInd); ;
}
m_bIsConnectDevice[deviceInd] = (SOCKET_ERROR != iRet);
m_bIsGetDeviceReady = FALSE;
}