Socket中如何设置连接超时(转)
http://tangfeng.iteye.com/blog/795497
Socket中可以使用select设置连接超时,需要先将socket设置为非锁定模式,这样,在connect时,才会立马跳过,同时,通常也会产生一个WSAEWOULDBLOCK错误,这个错误没关系。再执行select则是真正的超时。
- WSADATA wsd;
- SOCKET cClient;
- int ret;
- struct sockaddr_in server;
- hostent *host = NULL;
- if (WSAStartup(MAKEWORD(2,0), &wsd))
- {
- return 0;
- }
- cClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (cClient == INVALID_SOCKET)
- {
- return 0;
- }
- // set Recv and Send time out
- DWORD TimeOut = 6000; // 设置发送超时6秒
- if (::setsockopt(cClient, SOL_SOCKET, SO_SNDTIMEO, (char *)&TimeOut, sizeof(TimeOut)) == SOCKET_ERROR)
- {
- return 0;
- }
- TimeOut = 6000; // 设置接收超时6秒
- if (::setsockopt(cClient, SOL_SOCKET, SO_RCVTIMEO, (char *)&TimeOut, sizeof(TimeOut)) == SOCKET_ERROR)
- {
- return 0;
- }
- // 设置非阻塞方式连接
- unsigned long ul = 1;
- ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul);
- if (ret == SOCKET_ERROR)
- return 0;
- // 连接
- server.sin_family = AF_INET;
- server.sin_port = htons(25);
- server.sin_addr.s_addr = inet_addr((LPCSTR)pSmtp);
- if (server.sin_addr.s_addr == INADDR_NONE)
- return 0;
- connect(cClient, (const struct sockaddr*)&server, sizeof(server));
- // select 模型,即设置超时
- struct timeval timeout ;
- fd_set r;
- FD_ZERO(&r);
- FD_SET(cClient, &r);
- timeout.tv_sec = 15; // 连接超时15秒
- timeout.tv_usec = 0;
- ret = select(0, 0, &r, 0, &timeout);
- if (ret <= 0)
- {
- ::closesocket(cClient);
- return 0;
- }
- // 一般非锁定模式套接字比较难控制,可以根据实际情况考虑再设回阻塞模式
- unsigned long ul1 = 0;
- ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul1);
- if (ret == SOCKET_ERROR)
- {
- ::closesocket(cClient);
- return 0;
- }