用堵塞的winsock怎么加超时处理 例如recv()等了一个小时还没有收到数据,怎么跳出 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 1. 用setsockopt函数设置超时。2. 或用WM_TIMER设置定时器,到时间了就调用WSACancelBlockingCall取消阻塞调用,这样recv就会返回,返回值是一个特别的值,这个查查Msdn就知道了。3. 用select语句对socket句柄进行数据检查。这是unix socket编程的经典方法,windows也支持。 setsockopt()怎么设置,在什么时候设置,可否给个例子 int TimeOut=6000; //收发超时3秒 if(!SetSockOpt(SO_SNDTIMEO,(char *)&TimeOut, sizeof(TimeOut))) { return FALSE; } To:farfh(慕容长风) 我开了一个收数据的线程,要设置recv()超时,SetSockOpt()要放在何处呢 timeval read_timeout ; fd_set read_fd; read_timeout.tv_sec = 5; read_timeout.tv_usec = 0; FD_ZERO(&read_fd); FD_SET(m_hWriterSocket,&read_fd); nErr = ::select(0,&read_fd,0,0,&read_timeout); if (nErr ==0) { //MessageBox(); goto ConnectBreak; } if( nErr == SOCKET_ERROR ) { //MessageBox(); goto ConnectBreak; } nErr = ::recv(m_hWriterSocket, getbuf(), LengthNeedRead, 0); if (nErr ==0) { //MessageBox(); goto ConnectBreak; } else{ if( nErr == SOCKET_ERROR ) { //MessageBox(); goto ConnectBreak; } else{ //do you process } } int Timeout=60000connect_flag_cmd= connect(cmdsock,(struct sockaddr FAR *)&from,sizeof(from));status=setsockopt(cmdsock,IPPROTO_TCP, SO_RCVTIMEO, (char *)&Timeout, sizeof(Timeout));status=-1,setsockopt失败,为什么 好象是WinSock不支持SO_RCVTIMEO.试试用:/*返回:>0: 接收长度other: failed*/int sockRecvBuf(int sock,char *pszBuf,int iMaxLen,int rcvTmOut){ int retval; struct timeval timeVal; fd_set setId; if(rcvTmOut>0) { timeVal.tv_sec=rcvTmOut; timeVal.tv_usec=0; FD_ZERO(&setId); FD_SET((unsigned)sock,&setId); retval=select(0,&setId,NULL,NULL,&timeVal); if(retval==SOCKET_ERROR)return -1; if(retval==0)return 0; //time out //if(!FD_ISSET(sock,&setId))return 0; } retval=recv(sock,pszBuf,iMaxLen,0); if(retval<0) { strcpy(gszErrMsg,"receive error"); return -2; } return(retval);} 用select太费了,如果是我的话我宁愿则EVENT,异步收发,这样也较简单。给个MFC下完整代码,使用API的道理是一样的。一般说来是没问题的,总之要先setsockopt,才能connect,详见msdn。CCFSocket sk; if(!sk.Create()) { MsgBox("连接时候出现错误,请尝试从新连接"); sk.Close(); return FALSE; } if(!sk.AsyncSelect(0)) { return FALSE; } DWORD ld=0; if(!sk.IOCtl(FIONBIO ,&ld)) { return FALSE; } int TimeOut=6000; //收发超时6秒 if(!sk.SetSockOpt(SO_SNDTIMEO,(char *)&TimeOut, sizeof(TimeOut))) { return FALSE; } if(!sk.SetSockOpt(SO_RCVTIMEO,(char *)&TimeOut, sizeof(TimeOut))) { return FALSE; } return TRUE; if(!sk.Connect(m_Ip,SERVER_PORT)) { sk.Close(); return FALSE; } 附带说一句,在WINDOWS下编程,所有错误都可以使用WSAGetLastError()或者GetLastError()查出错误来,如果设置没有成功,请检查错误代码。 是不是每次调用recv()之前都要调用一次select()?select()会不会象WSAAsyncSelect()一样把socket变成非堵塞 int Timeout=6000;connect_flag_cmd= connect(cmdsock,(struct sockaddr FAR *)&from,sizeof(from)); timeVal.tv_sec=Timeout; timeVal.tv_usec=0; FD_ZERO(&setId); FD_SET((unsigned)cmdsock,&setId); retval=select(0,&setId,NULL,NULL,&timeVal);按F5,运行到select()就堵住了,为什么 Matlab图像嵌入VC界面时遇到的问题 急救!!!使用CObArray的问题。。。 MSCHART问题 关于类协作安装程序注册入口函数调用不成功的问题,各位大哥帮忙看看。 初学ActiveX,介绍几个好的资源 调试问题,望大侠们多多指教。 100份求教,如何用用vc实现在网页上绘制直线等图形的功能(类似imarkup的功能)? 想学COM,不知道现在我这种状况行不行? 新手第一次用VC++写程序《双缓冲 判断点是否进入矩形区域》 如何在VC60下生成dll文件 在 WINDOWS NT操作系统下如何实现对并口的操作 问一个关于红外编程的问题
这样recv就会返回,返回值是一个特别的值,这个查查Msdn就知道了。3. 用select语句对socket句柄进行数据检查。这是unix socket编程的经典方法,windows也支持。
if(!SetSockOpt(SO_SNDTIMEO,(char *)&TimeOut,
sizeof(TimeOut)))
{
return FALSE;
}
我开了一个收数据的线程,要设置recv()超时,SetSockOpt()要放在何处呢
fd_set read_fd; read_timeout.tv_sec = 5;
read_timeout.tv_usec = 0; FD_ZERO(&read_fd);
FD_SET(m_hWriterSocket,&read_fd); nErr = ::select(0,&read_fd,0,0,&read_timeout);
if (nErr ==0)
{
//MessageBox();
goto ConnectBreak;
}
if( nErr == SOCKET_ERROR )
{
//MessageBox();
goto ConnectBreak;
}
nErr = ::recv(m_hWriterSocket,
getbuf(),
LengthNeedRead,
0);
if (nErr ==0)
{
//MessageBox();
goto ConnectBreak;
}
else{
if( nErr == SOCKET_ERROR )
{
//MessageBox();
goto ConnectBreak;
}
else{
//do you process
}
}
connect_flag_cmd= connect(cmdsock,(struct sockaddr FAR *)&from,sizeof(from));
status=setsockopt(cmdsock,IPPROTO_TCP, SO_RCVTIMEO, (char *)&Timeout, sizeof(Timeout));status=-1,setsockopt失败,为什么
/*
返回:
>0: 接收长度
other: failed
*/
int sockRecvBuf(int sock,char *pszBuf,int iMaxLen,int rcvTmOut)
{
int retval;
struct timeval timeVal;
fd_set setId; if(rcvTmOut>0)
{
timeVal.tv_sec=rcvTmOut;
timeVal.tv_usec=0; FD_ZERO(&setId);
FD_SET((unsigned)sock,&setId); retval=select(0,&setId,NULL,NULL,&timeVal);
if(retval==SOCKET_ERROR)return -1;
if(retval==0)return 0; //time out
//if(!FD_ISSET(sock,&setId))return 0;
} retval=recv(sock,pszBuf,iMaxLen,0);
if(retval<0)
{
strcpy(gszErrMsg,"receive error");
return -2;
} return(retval);
}
给个MFC下完整代码,使用API的道理是一样的。一般说来是没问题的,总之要先setsockopt,才能connect,详见msdn。
CCFSocket sk;
if(!sk.Create())
{
MsgBox("连接时候出现错误,请尝试从新连接");
sk.Close();
return FALSE;
}
if(!sk.AsyncSelect(0))
{
return FALSE;
}
DWORD ld=0;
if(!sk.IOCtl(FIONBIO ,&ld))
{
return FALSE;
}
int TimeOut=6000; //收发超时6秒
if(!sk.SetSockOpt(SO_SNDTIMEO,(char *)&TimeOut,
sizeof(TimeOut)))
{
return FALSE;
}
if(!sk.SetSockOpt(SO_RCVTIMEO,(char *)&TimeOut,
sizeof(TimeOut)))
{
return FALSE;
}
return TRUE;
if(!sk.Connect(m_Ip,SERVER_PORT))
{
sk.Close();
return FALSE;
}
select()会不会象WSAAsyncSelect()一样把socket变成非堵塞
connect_flag_cmd= connect(cmdsock,(struct sockaddr FAR *)&from,sizeof(from));
timeVal.tv_sec=Timeout;
timeVal.tv_usec=0;
FD_ZERO(&setId);
FD_SET((unsigned)cmdsock,&setId);
retval=select(0,&setId,NULL,NULL,&timeVal);
按F5,运行到select()就堵住了,为什么