散分了!!!!!关于winsock超时处理的问题!

himming 2002-09-02 01:21:15
在写一个网络传输的程序时,想要知道怎样才能控制connect连接超时时间,比如,我可以设定一个变量m_iTimeOut = 30;这样在connect进行最长30秒的尝试,之后返回错误!望给出详细代码!
...全文
429 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
himming 2002-09-02
  • 打赏
  • 举报
回复
好了,谢谢!
himming 2002-09-02
  • 打赏
  • 举报
回复
下面是我的实现代码:
char sBuf[2048];
int i;
int iSRTimeOut = 6000;
u_long arg=1;
rc4_key key;
int r;
struct sockaddr_in sockaddr;
sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (sock==INVALID_SOCKET)
{
r=WSAGetLastError();
closesocket(sock);
sprintf(sBuf,"Winsock Error:%d",r);
return Error(_T(sBuf));
}
//设置接收超时6000毫秒
if(setsockopt(sock,IPPROTO_TCP,SO_RCVTIMEO,(const char FAR*)&iSRTimeOut,sizeof(int))==SOCKET_ERROR)
{
r=WSAGetLastError();
closesocket(sock);
sprintf(sBuf,"Winsock Error:%d",r);
//return Error(_T(sBuf));
}
//设置发送超时6000毫秒
if(setsockopt(sock,IPPROTO_TCP,SO_SNDTIMEO,(const char FAR*)&iSRTimeOut,sizeof(int))==SOCKET_ERROR)
{
r=WSAGetLastError();
closesocket(sock);
sprintf(sBuf,"Winsock Error:%d",r);
//return Error(_T(sBuf));
}
//设置非阻塞连接方式
unsigned long ul = 1;
r = ::ioctlsocket(sock, FIONBIO, (unsigned long*)&ul);
if(r==SOCKET_ERROR)
{
r=WSAGetLastError();
closesocket(sock);
sprintf(sBuf,"Winsock Error:%d",r);
// return Error(_T(sBuf));
}

//进行连接操作
switch (m_ProxyType)
{
case 0:
sockaddr.sin_addr.s_addr=inet_addr(m_SvrAddr);
sockaddr.sin_port=htons((unsigned short)m_SvrPort);
break;
default:
sockaddr.sin_addr.s_addr=inet_addr(m_ProxyAddr);
sockaddr.sin_port=htons((unsigned short)m_ProxyPort);
break;
}
sockaddr.sin_family=AF_INET;
memset(sockaddr.sin_zero,0,8);
int iReturn;
connect(sock,(struct sockaddr*)&sockaddr,sizeof(struct sockaddr_in));

iReturn = ConnectedReady(sock);// 连接延时
if(iReturn == 0)
{
return Error(_T("Connect TimeOut!"));
}
if(iReturn >1)
{
sprintf(sBuf,"Winsock Error:%d",iReturn);
return Error(_T(sBuf));
}
//设置回阻塞模式
unsigned long ul1= 0 ;
r = ioctlsocket(sock, FIONBIO, (unsigned long*)&ul1);
if(r==SOCKET_ERROR)
{
r=WSAGetLastError();
closesocket (sock);
sprintf(sBuf,"Winsock Error:%d",r);
return Error(_T(sBuf));
}


说明:进行setsockopt、设置非阻塞模式、一直到最后设置回阻塞模式,都有错误码返回!
功能描述:本来我的程序就是要实现:自己定义一个timeout值,在网络不通或阻塞时,客户端调用connect,最长等待timeout秒。

msn:himming@hotmail.com
LocalVar 2002-09-02
  • 打赏
  • 举报
回复
不行你再找我,返回的错误值是什么。
LocalVar 2002-09-02
  • 打赏
  • 举报
回复
这个应该是可以用的,因为我用过,我的代码是这样的,供你参考

LPHOSTENT ScanIPAddr(DWORD dwIP)
{
SOCKET sock = INVALID_SOCKET;
LPHOSTENT lphost = NULL;
SOCKADDR_IN server;
u_long ul = 1;
struct timeval timeout ;
fd_set r;

memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = _nPort;
server.sin_addr.s_addr = htonl((u_long)dwIP);

sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sock == INVALID_SOCKET)
return NULL;

//设置非阻塞方式连接
if(ioctlsocket(sock, FIONBIO, (u_long*)&ul)==SOCKET_ERROR)
return NULL;

if(0 != connect(sock, (SOCKADDR*)&server, sizeof(server)))
{
if(WSAGetLastError() != WSAEWOULDBLOCK)
{
closesocket(sock);
return NULL;
}
}

//select 模型,即设置超时
FD_ZERO(&r);
FD_SET(sock, &r);
timeout.tv_sec = 0; //连接超时0秒
timeout.tv_usec = 700;
if(select(0, 0, &r, 0, &timeout) <= 0)
{
closesocket(sock);
return NULL;
}

lphost = gethostbyaddr((const char *)&(server.sin_addr), 4, AF_INET);
closesocket(sock);

return lphost;
}
himming 2002-09-02
  • 打赏
  • 举报
回复
不行,返回的都是错误!!
LocalVar 2002-09-02
  • 打赏
  • 举报
回复
看到这一页最下面的 管理|关闭窗口 了吗?点击管理就可以给分了.
himming 2002-09-02
  • 打赏
  • 举报
回复
谢谢先!我试试看!
怎么给分呀?我从来都没干过!
教我!我给大家散!
知道方向的感觉真好!:)
ksyou 2002-09-02
  • 打赏
  • 举报
回复
学习
ornot 2002-09-02
  • 打赏
  • 举报
回复
还是不用要select的好,用WSAEVENT可能要好一点 (:
LocalVar 2002-09-02
  • 打赏
  • 举报
回复
// Socket中如何设置连接超时
// AntGhazi/2001.12.14 主页:antghazi.yeah.net
/*
把CSDN与中文yahoo翻了底朝天, 也没找到如何设置socket的连接超时的满意方法, 问此问题的兄弟已有一大堆,
这里偶就讲一下win下如何设置socket的connect超时. 设置connect的超时很简单, CSDN上也有人提到过使用select,
但却没有一个令人满意与完整的答案. 偶所讲的也正是select函数, 此函数集成在winsock1.1中, 简单点讲,"作用使
那些想避免在套接字调用过程中被锁定的应用程序, 采取一种有序的方式, 同时对多个套接字进行管理"
(<<Windows网络编程技术>>原话). 使用方法与解释请见《Windows网络编程技术》.
在使用此函数前, 需先将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
int 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;
}

/////////////////////////////////////////////////////////////////
以前我从csdn上找到的,注意如果调用connect返回SOCKET_ERROR,那么你要调用 WSAGetLastError(),看错误是不是WSAEWOULDBLOCK,如果是,则忽略,否则是真的出错了。
zhaoyao73 2002-09-02
  • 打赏
  • 举报
回复
不知道WinSock有没有异步connect

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧