udp奇异的异常!接收数据总是在关闭句柄之后才过来?
udp客户端向服务器发送一个udp数据包,服务器返回,客户端等待N秒钟,在N秒之内等待数据到来,然后我用wireshark抓包。
不管N是2秒还是20秒,抓包显示,总是在客户端关闭了udp的连接句柄之后,wireshark刷的一下查询到udp应答包了,奇怪呀,谁能看看是什么问题?代码如下,关键部分在while(1)往后~~~~~~~~~~
- C/C++ code
/********************************** Code ************************************/BOOL __stdcall myfunction(int m_wait, void(WINAPI *notify)(int devtype,char *m_sername,char *m_url,BYTE m_mac[6],WORD m_webport,WORD m_localport, char *m_submask,char *m_getway,char *m_multiip,char *m_dns,WORD m_multiport,int channel),char *localurl){ int s_sendrand; BOOL RetVal = FALSE; unsigned int timenow,presec; NETBOARDMSG_SEARCH_RET *pSearchRet; char ipvs_url[20]; char ipvs_submask[20]; char ipvs_getway[20]; char ipvs_multiurl[20]; char ipvs_dns[20]; int iRet; fd_set fdRead; struct timeval timeout; NET_MSG_BUFF pMsgBuff; struct sockaddr_in LocalAddr; struct ip_mreq stMreq; SOCKET s_boardmsg = INVALID_SOCKET; char ttl = (char)32; unsigned long addr; char localip[20]; strcpy(localip,"0.0.0.0"); if(localurl) strcpy(localip,localurl); srand(time(NULL)); s_sendrand = rand(); if((s_boardmsg = socket(AF_INET,SOCK_DGRAM,0)) == INVALID_SOCKET) { goto exit_cam; } memset(&LocalAddr,0,sizeof(LocalAddr)); LocalAddr.sin_family = AF_INET; LocalAddr.sin_addr.s_addr = inet_addr(localip); LocalAddr.sin_port = htons(BOARDCLIENTPORT); if(bind(s_boardmsg, (struct sockaddr*)&LocalAddr, sizeof(LocalAddr)) == SOCKET_ERROR) { goto exit_cam; } setsockopt(s_boardmsg,IPPROTO_IP,IP_MULTICAST_TTL,&ttl,sizeof(ttl)); addr = inet_addr(localip); setsockopt(s_boardmsg, IPPROTO_IP, IP_MULTICAST_IF,(char *)&addr, sizeof(addr)); stMreq.imr_multiaddr.s_addr = inet_addr(BOARDURL_MULTI); stMreq.imr_interface.s_addr = inet_addr(localip); if(setsockopt(s_boardmsg, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&stMreq, sizeof(stMreq)) <0) { printf("Join a multicast group failed!\n"); goto exit_cam; } pMsgBuff.pMsgHead.nChannel = s_sendrand; pMsgBuff.pMsgHead.dwDataSize = 0; pMsgBuff.pMsgHead.nTypeMain = NETBOARDMSG_SEARCH; pMsgBuff.pMsgHead.pMask1 = MSGHEAD_MASK1; pMsgBuff.pMsgHead.pMask2 = MSGHEAD_MASK2; memset(&LocalAddr,0,sizeof(LocalAddr)); LocalAddr.sin_family = AF_INET; LocalAddr.sin_addr.s_addr = inet_addr(BOARDURL_MULTI); LocalAddr.sin_port = htons(BOARDSERVERPORT); sendto(s_boardmsg,(char*)&pMsgBuff,sizeof(NET_MSG_HEAD),0, (struct sockaddr*)&LocalAddr,sizeof(LocalAddr)); pSearchRet = (NETBOARDMSG_SEARCH_RET*)pMsgBuff.pMsgBuff; timeout.tv_sec = m_wait / 1000; timeout.tv_usec = m_wait % 1000; RetVal = TRUE; presec = timeGetTime(); while(1) ////////等待响应的部分从这里开始 { timenow = timeGetTime(); if((timenow - presec) >= m_wait) { OutputDebugStr("超时结束\n"); break; } fdRead.fd_count = 1; fdRead.fd_array[0] = s_boardmsg; iRet = select(0,&fdRead,NULL,NULL,&timeout); if(iRet == 0) {OutputDebugStr("继续\n"); continue; } iRet = recv(s_boardmsg,(char*)&pMsgBuff, sizeof(NET_MSG_HEAD) + sizeof(NETBOARDMSG_SEARCH_RET),0); char sz[100]; sprintf(sz, "hhhhhhh:%d\n", iRet); OutputDebugStr(sz); if((iRet == (sizeof(NET_MSG_HEAD) + sizeof(NETBOARDMSG_SEARCH_RET))) && (s_sendrand == pMsgBuff.pMsgHead.nChannel) ) { if(pMsgBuff.pMsgHead.pMask1 != MSGHEAD_MASK1 || pMsgBuff.pMsgHead.pMask2 != MSGHEAD_MASK2 || pMsgBuff.pMsgHead.nTypeMain != NETBOARDMSG_SEARCH) continue; LocalAddr.sin_addr.s_addr = pSearchRet->url; strcpy(ipvs_url,inet_ntoa(LocalAddr.sin_addr)); LocalAddr.sin_addr.s_addr = htonl(pSearchRet->submask); strcpy(ipvs_submask,inet_ntoa(LocalAddr.sin_addr)); LocalAddr.sin_addr.s_addr = pSearchRet->getway; strcpy(ipvs_getway,inet_ntoa(LocalAddr.sin_addr)); LocalAddr.sin_addr.s_addr = pSearchRet->multiip; strcpy(ipvs_multiurl,inet_ntoa(LocalAddr.sin_addr)); LocalAddr.sin_addr.s_addr = pSearchRet->dns; strcpy(ipvs_dns,inet_ntoa(LocalAddr.sin_addr)); if(notify) { notify( pSearchRet->devtype,pSearchRet->sername,ipvs_url,pSearchRet->mac, pSearchRet->wPortWeb,pSearchRet->wPortSer, ipvs_submask,ipvs_getway,ipvs_multiurl,ipvs_dns,pSearchRet->wPortMulti,pSearchRet->channel); } } }exit_cam: if(s_boardmsg != INVALID_SOCKET) { stMreq.imr_multiaddr.s_addr = inet_addr(BOARDURL_MULTI); stMreq.imr_interface.s_addr = inet_addr(localip); setsockopt(s_boardmsg, IPPROTO_IP, IP_DROP_MEMBERSHIP,(char*)&stMreq, sizeof(stMreq)); closesocket(s_boardmsg); OutputDebugStr("这里\n"); } OutputDebugStr("这里2\n"); return RetVal;}
[解决办法]
iRet = recv(s_boardmsg,(char*)&pMsgBuff//换成recvfrom再试
[解决办法]
你联系我,QQ 24508609我和你一起测试一下。