读书人

UDP recvfrom始终返回-1解决方案

发布时间: 2012-04-01 17:23:46 作者: rapoo

UDP recvfrom始终返回-1
UDP客户端,在主线程初始化,新开一线程循环接收服务器端发来的数据

C/C++ code
const char* IP = "127.0.0.1";    ///< 服务器IPUSHORT    PORT = 7777;        ///< 服务器端口号SOCKET g_sockClient;SOCKADDR_IN g_addrSrv;void main(){    g_RecvData = new _RecvMsgData;    g_recv = new char[1024];    WSADATA wsaData;        if (WSAStartup(MAKEWORD(2,2), &wsaData)!= NO_ERROR)    {        return;    }    if (LOBYTE( wsaData.wVersion ) != 2 ||        HIBYTE( wsaData.wVersion ) != 2)    {        WSACleanup();        return;    }    // 创建socket    SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, 0);    if (sockClient == INVALID_SOCKET)    {        WSACleanup();        return;    }    SOCKADDR_IN addrSrv; // 服务器IP及端口号信息    addrSrv.sin_addr.S_un.S_addr = inet_addr(IP); // 测试时使用本机    addrSrv.sin_family = AF_INET;    addrSrv.sin_port = htons(PORT);    g_sockClient = sockClient;    g_addrSrv = addrSrv;    unsigned int threadID;    unsigned long ret = _beginthreadex(NULL, 0, DataProc, NULL, 0, &threadID);         if (ret == 0) // 开辟数据处理线程失败    {        AfxMessageBox("开辟数据处理线程失败,退出");        return;    }}unsigned int WINAPI __stdcall DataProc(void *pParam){    int len = 0;    int ret;    unsigned char temp[1024];     int i;    while(1)   {       ret = recvfrom(g_sockClient, g_recv, 1024, 0, (sockaddr*)(&g_addrSrv), &len);       if (ret == SOCKET_ERROR) // 网络出错       {          int err = WSAGetLastError();          cout<<"WSAGetLastError()="<<err<<endl;          return 0;      }      else      {          ...      }   }}


出现的问题是:可以正常给服务器发送数据,但是recvfrom一直返回-1,WSAGetLastError()始终返回0.
而我希望的是能够使线程阻塞在recvfrom那儿,只有有数据来到才返回。
请问该怎么实现?谢谢!

[解决办法]
你得先bind一个端口
[解决办法]
仔细看看MSDN的例子
C/C++ code
#include <stdio.h>#include "winsock2.h"void main() {  WSADATA wsaData;  SOCKET RecvSocket;  sockaddr_in RecvAddr;  int Port = 27015;  char RecvBuf[1024];  int  BufLen = 1024;  sockaddr_in SenderAddr;  int SenderAddrSize = sizeof(SenderAddr);  //-----------------------------------------------  // Initialize Winsock  WSAStartup(MAKEWORD(2,2), &wsaData);  //-----------------------------------------------  // Create a receiver socket to receive datagrams  RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);  //-----------------------------------------------  // Bind the socket to any address and the specified port.  RecvAddr.sin_family = AF_INET;  RecvAddr.sin_port = htons(Port);  RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);  bind(RecvSocket, (SOCKADDR *) &RecvAddr, sizeof(RecvAddr));  //-----------------------------------------------  // Call the recvfrom function to receive datagrams  // on the bound socket.  printf("Receiving datagrams...\n");  recvfrom(RecvSocket,     RecvBuf,     BufLen,     0,     (SOCKADDR *)&SenderAddr,     &SenderAddrSize);  //-----------------------------------------------  // Close the socket when finished receiving datagrams  printf("Finished receiving. Closing socket.\n");  closesocket(RecvSocket);  //-----------------------------------------------  // Clean up and exit.  printf("Exiting.\n");  WSACleanup();  return;}
[解决办法]
你首先要搞清楚原理
UDP是无连接的
作为客户端发数据用sendto收数据跟服务端一样都用recvfrom
客户端向服务器端发送一包数据后接下来就可以用recvfrom
来接收服务器端发来的回应,然而你此处并没有向服务器端发送任何数据
那么这个socket的临时通信信道根本就没有建立起来,recvfrom根本无意义
除非你是服务器端等待数据请求
[解决办法]
客户端也要bind,不然别人怎么给你发数据,往哪里发?


[解决办法]
楼主的客户端其实算一个服务器端,需要bind才能收回信息,不然“服务器端”发来的东西,“客户端”也不知道怎么接收。

如果你用tcp,建立了连接,那么客户端可以发送过去,再通过同一个socket接收回来,这样没问题,也不用bind
但udp没有建立这个连接。
[解决办法]
对udp来说,只要你血药接收数据,就要bind。

读书人网 >VC/MFC

热点推荐