目的1:socket 連接超時設置(connect)
通過select來管理socket進行超時設置
WSAStartup(MAKEWORD(2, 2), &data);
sock=socket(AF_INET,SOCK_STREAM,0); //初始化套接字 ip類型-> AF_INET:IPV4 AF_INET6:IPV6
memset(&server_add,0,sizeof(sockaddr_in));
server_add.sin_family=AF_INET; //ip使用IPV4
server_add.sin_addr.S_un.S_addr=inet_addr(DEV_ip); //IP 地址
server_add.sin_port=htons(atoi(DEV_port)); //端口
//設置發送和接收超時
timeval tv_timeout;
tv_timeout.tv_sec=200; //秒
tv_timeout.tv_usec=0; //微秒 1秒=100W微秒
int timeout=5;
unsigned long on = 1; //1 非阻塞 0 阻塞
if(ioctlsocket(sock, FIONBIO, &on)<0) //設置爲非阻塞模式
{
AfxMessageBox("設爲非阻塞失敗\n");
goto end;
}
if(connect(sock,(struct sockaddr*)&server_add,sizeof(server_add))==SOCKET_ERROR)
{
#ifdef WIN32
if (GetLastError()==WSAEWOULDBLOCK)//10035
#else
if (errno==EINPROGRESS)
#endif
{
fd_set set;
int error;
int len=sizeof(int);
struct timeval tv;
tv.tv_sec=10; //秒
tv.tv_usec=0;
FD_ZERO(&set);
FD_SET(sock,&set);
int ret=select(sock+1,NULL,&set,NULL,&tv);
if (ret>0) //連接成功
{
getsockopt(sock,SOL_SOCKET,SO_ERROR,(char*)&error,(socklen_t *)&len);
if (error!=0)
{
AfxMessageBox(error);
goto end;
}
}
else if(ret==0) //超時
{
AfxMessageBox("連接"+DEV_ip+"超時,請檢查網絡");
goto end;
}
else if(ret==-1) //連接出錯
{
AfxMessageBox("連接"+CString(DEV_ip+":"+DEV_port)+"服務器失敗\n");
goto end;
}
}
else
{
on=0;
if(ioctlsocket(sock,FIONBIO,&on)<0)
{
AfxMessageBox("還原阻塞失敗\n");
goto end;
}
}
}
//else
{
}
//連接上了 將socket設爲阻塞
on=0;
if(ioctlsocket(sock,FIONBIO,&on)<0)
{
AfxMessageBox("還原阻塞失敗\n");
goto end;
}
目的2:發送和接收超時
//設置發送和接收超時
struct timeval tv_timeout;
tv_timeout.tv_sec=10; //秒
tv_timeout.tv_usec=0; //微秒 1秒=100W微秒
if(setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,(const char*)&tv_timeout,sizeof(timeval))<0)
{
AfxMessageBox("設置發送超時失敗");
goto end;
}
if(setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(const char*)&tv_timeout,sizeof(timeval))<0)
{
AfxMessageBox("設置接收超時失敗");
goto end;
}
//發送請求
if(send(sock,cxXMLBuf,cxXMLBufLen,0)<0)
{
CString msg;
//AfxMessageBox("查詢設備信息:發送請求失敗,請檢查網絡狀態"+GetLastError());
msg.Format("%d",GetLastError());
AfxMessageBox(msg);
goto end;
}
//接收請求
ret=recv(sock,recvBuf,recvBufLen,0);
if(ret==-1)
{
AfxMessageBox("接收數據失敗");
goto end;
}
但是網絡稍有不好,recv立馬就報錯了,錯誤碼是10057也就是發送超時,可是我timeout 明明設置的是10秒啊,1秒都沒到就超時了?
查閱各種資料,一直都認爲超時中的timeval->tv_se是秒,而且在連接超時已經驗證了,可是到這怎麼就不生效了呢?
timeval定義,看着也是沒問題的。
/*
* Structure used in select() call, taken from the BSD file sys/time.h.
*/
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* and microseconds */
};
後來我把tv_se設置成一個超大數,如100000,這樣就能正常接收數據了(6-8秒接收完畢),再測試測試發現這個參數當成毫秒來計算了,我去,顛覆啊~~~,那前邊的怎麼解釋呢,我也不知道~!!!!!