如何设置TCP sokcet连接的超时时间??connect
我搜索过csdn以前的页面,在google里面也搜索过了,只有这一种办法,就是这个帖子里面提到的:
http://community.csdn.net/Expert/topic/3153/3153187.xml?temp=.0183832
但是我试下来,如果去连接一个存在的ip地址,那么connect函数返回一个 10035错误,即 无法立即完成一个非阻塞套接字的操作,但是如果去连接一个不存在的地址,那么connect函数一样会阻塞30秒,那么这样一来的话,这种方法就变得毫无意义.
比如:局域网里面有一台电脑IP为192.168.0.1,用这种办法去连接的话,超时时间是可以设置的
但是我去connect 192.168.0.183 这个不存在的IP地址,那么一样会阻塞30秒!
能解决吗?
问题点数:100、回复次数:11Top
1 楼krh2001(边城浪子)回复于 2005-06-10 16:29:37 得分 10
本来就是这样的,IP地址是否存在,本来就是看它有没有响应. 不能一下子就确定这是一个不存在的IP的所以要多给点时间它. 30秒 并不算很多Top
2 楼aiyue2010(亚伦)回复于 2005-06-10 16:38:39 得分 5
同意楼上
发送SYN后就是看对方有没有返回ACKTop
3 楼goodboyws(深夜不眠者(VCMVP))回复于 2005-06-10 16:46:38 得分 3
应该先ping一下, windows网络编程里有一个介绍怎么做ping的例子Top
4 楼eastnofail(Char *)回复于 2005-06-10 16:49:43 得分 0
用ping是不行的,如果对方安装了防火墙,禁止了ping,但是允许我的程序通讯,那样的话,就会误认为是网络不通Top
5 楼fisker0303(天塌了,地陷了,小花狗不见了.)回复于 2005-06-10 19:10:53 得分 40
krh2001(边城浪子)说的对,楼主应该知道连接一个远程服务器的原理,第一级路由器上如果找不到申请的ip地址,它就要向上一级路由器汇报,... ...
所以,30秒真的并不长。Top
6 楼fisker0303(天塌了,地陷了,小花狗不见了.)回复于 2005-06-10 19:13:46 得分 36
如果真的不想等30秒那么久,并且你确定等n秒后,如果连接不上,就可以宣布连接失败,可不可以这样。
在一个线程中连接,并设置定时器,
connect ... ...;
取消定时器;
定时器触发后,可以通知用户,连接失败,但实际上,connect还在阻塞中。Top
7 楼softrain(曾经的月光,现在的日光)回复于 2005-06-10 19:47:51 得分 1
使用异步事件模型,或者异步窗口模型Top
8 楼krh2001(边城浪子)回复于 2005-06-10 19:53:06 得分 2
如果你确定,真的不需要等这么久,或者用户希望可以随时中上连接过程,那么一般是用 非阻塞模式来做的. 看看我的这段连接代码(节选),可以作为TCP连接的典范:
bool CRemoteLink::Connect()
{
OnDisconnected(); // 如果已经连接,则断开
if(!m_bUseProxy)
{
m_iConnStatus = SS_CONNECTING; // 正在连接状态
GNTRACE ("开始连接到远程服务器[%s][%ld]...\n", m_strip.c_str(), m_port);
// 建立套接字, 准备连接到服务器
m_socket = ::socket(AF_INET, SOCK_STREAM, 0);
if (socket < 0) {
if(m_pCallBack)
m_pCallBack->OnSocketError(SE_CREATE, MSG_SE_CREATE);
return false;
}
// 设为异步操作方式
unsigned long on = 1;
if (::ioctlsocket(m_socket, FIONBIO, &on) < 0) {
::closesocket(m_socket);
if(m_pCallBack)
m_pCallBack->OnSocketError(SE_CREATE, MSG_SE_CREATE);
return false;
}
sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(m_strip.c_str());
addr.sin_port = htons(m_port);
int rt;
rt = ::connect(m_socket, (sockaddr *) &addr, sizeof(addr));
if (rt == 0) {
OnConnected();
return true;
}
// ==================================================================
timeval to;
// 首先建立连接
fd_set wfds;
fd_set efds;
FD_ZERO(&wfds);
FD_ZERO(&efds);
// test shutdown event each 100ms.
to.tv_sec = 0; // CONNECT_TIMEOUT;
to.tv_usec = 100000;
int it = 0;
while(!m_meShutdown.Wait(0) && !m_meConnStop.Wait(0))
{
FD_SET(m_socket, &wfds);
FD_SET(m_socket, &efds);
int n = select(m_socket + 1, NULL, &wfds, &efds, &to);
if (n > 0) {
if(FD_ISSET(m_socket, &wfds))
{
OnConnected();
return true;
}
else
{
//int err = ::WSAGetLastError();
//const char* msg = GetLastErrorMessage(err);
GNTRACE ("CRemoteLink::Connect : connection attempt failed!\n");
if(m_pCallBack)
m_pCallBack->OnSocketError(SE_CONN, MSG_SE_CONN);
break;
}
} else if (n < 0) { // Select Error
int err = ::WSAGetLastError();
const char* msg = GetLastErrorMessage(err);
GNTRACE ("CRemoteLink::Connect : Select Error.[%d] - %s\n", err, msg);
if(m_pCallBack)
m_pCallBack->OnSocketError(err, msg);
break;
}
else
{
it += 100;
if(it > 30000) // 连接超时 -- (30S)
{
GNTRACE ("CRemoteLink::Connect : Time out.\n");
if(m_pCallBack)
m_pCallBack->OnSocketError(SE_TIMEOUT, MSG_SE_TIMEOUT);
break;
}
}
}
if(m_meConnStop.Wait(0))
{
GNTRACE("连接过程进行时被取消。\n");
}
}
else
{
// 通过代理服务器连接
...... (以下太长, 省略)
Top
9 楼lianglp(寻找黄金分割点)回复于 2005-06-10 22:07:45 得分 2
用异步吧,当连接上后,也就是说connect()成功后会返回fd_connect消息事件,不过你先要设定此事件通知哦。Top
10 楼0011411(爱也许是假的,可是当时的快乐是真的。)回复于 2005-06-10 22:17:58 得分 1
okTop
11 楼horisly(SUN YAT-SEN UNIVERSITY (逸仙先生))回复于 2005-08-20 03:13:52 得分 0
markTop




