UDP端口未打开,sendto()失败后,recvfrom设置无效,直接返回错误码?

 

在项目中需要检测UDP是否打开,刚开始实现是定时发送数据包,recvfrom设置超时时间是1s。结果发现当UDP没有开启时(比如电脑开机后直接运行)recvfrom设置的超时时间无效,而是立即返回SOCKET_ERROR,recvfrom函数返回0。

recvfrom返回值为0有两种情况:
1.socket已经"温和"关闭(使用shutdown或者设置linear属性)
2.对方发送一个空数据,也就是对方发送的数据长度为0。这时socket也就可以接收到的,并且recvfrom返回值为0。

只有服务端的recvfrom接收的是所有外部发向这个端口号的信息的,客户端的recvfrom是根据socket里的信息来收的,是绑定过服务器IP和端口号的。


最后解决方法: 定时发送数据包,用WSAGetLastError()判断错误号是否是10054。

调用WSAGetLastError()返回的结果为0,GetLastError()也是返回0。原因:int err=WSAGetLastError();的调用必须放到其他系统函数调用之前,也就是说,出现错误后,第一时间存储WSAGetLastError结果,而不能调用其他函数之后再调用此函数。因为调用系统函数会清除WSAGetLastError,致使结果返回0.
 

代码:

	int TimeOut = 1000;
    //设置接受等待时间为TimeOut
	if(setsockopt(g_sock,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){
		return -1;
	}

	for(i=0; i<5; i++){
		memset(szBuff, 0, sizeof(szBuff));
		strcpy(szBuff,"Test the UDP connect!\r\n");
		ret = sendto(g_sock,szBuff,strlen(szBuff),0,(sockaddr *)&addrSend,sizeof(addrSend));
		printf("%d send data: %s to %s:%d \n",ret,szBuff,inet_ntoa(addrSend.sin_addr),ntohs(addrSend.sin_port));
		int nRecLen = sizeof(addrSend);
		//等待并接受来自B的数据
		memset(szBuff, 0, sizeof(szBuff));
		ret = recvfrom(g_sock,szBuff,256,0,(sockaddr *)&addrSend,&nRecLen);
		if(GetLastError() == 10054){
			Sleep(1000);
		}
		printf("ret  %d data: %s to %s:%d \n",ret, szBuff,inet_ntoa(addrSend.sin_addr),ntohs(addrSend.sin_port));
		if (ret > 0  && strcmp(szBuff, "The Battery board is working!\r\n")==0) {
			connectBoard = true;
			break;
		}
	}

参考:

https://bbs.csdn.net/topics/391937100

https://blog.csdn.net/tianbaowen/article/details/8485567

你可能感兴趣的:(项目错误整理)