windows connect、接收發送超時 setsocketopt

目的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秒接收完畢),再測試測試發現這個參數當成毫秒來計算了,我去,顛覆啊~~~,那前邊的怎麼解釋呢,我也不知道~!!!!!

* 如有遇到的朋友請注意了,同時歡迎大佬解答這個現象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章