C++ socket编程:SENDTO()和recvfrom()错误代码10038&在 '服务器' 绑定失败与10038

问题描述:

//UDP receiver 
int main() 
{ 
    WSAData wsaData; 
    SOCKET receivingSocket; 
    SOCKADDR_IN receiverAddr; 
    SOCKADDR_IN senderAddr; 
    int senderAddrSize = sizeof(senderAddr); 
    int port=51020; 
    char receiveBuf[1024]; 
    int bufLength=1024; 

    cout << "UDP receiver\n"; 

    //Initialize winsock 
    if (WSAStartup(MAKEWORD(2,2),&wsaData) != 0) 
    { 
     cout << "Failed. Error Code : " << WSAGetLastError(); 
     exit(EXIT_FAILURE); 
    } 
    cout << "Initialised\n";` 

    if(receivingSocket = socket(AF_INET, SOCK_DGRAM, 0) == INVALID_SOCKET) 
    { 
     cout << "Could not create socket :" << WSAGetLastError(); 
    } 
    cout << "Socket created.\n"; 

    //fill up SOCKADDR_IN structure 
    senderAddr.sin_port = htons(port); 
    senderAddr.sin_family = AF_INET; 
    senderAddr.sin_addr.s_addr = htonl(INADDR_ANY); 

    //Bind information with socket 
    bind(receivingSocket, (SOCKADDR*)&senderAddr, sizeof(senderAddr)); 

    while(1) 
    { 
     cout << "Waiting for message\n"; 

     //try to receive some data, this is a blocking call 
     if (recvfrom(receivingSocket, receiveBuf, 1024, 0, (SOCKADDR*)&senderAddr, &senderAddrSize)) == SOCKET_ERROR)) 
     { 
      cout << "recvfrom() failed with error code :" << WSAGetLastError(); 
      exit(EXIT_FAILURE); 
     } 
     cout << receiveBuf; 
    } 

    //Close socket 
    closesocket(receivingSocket); 
    WSACleanup(); 
    std::cin.get(); 
    return 0; 
} 

C++ socket编程:SENDTO()和recvfrom()错误代码10038&在 '服务器' 绑定失败与10038

//UDP server 
int main() 
{ 
    WSAData wsaData; 
    SOCKET sendingSocket; 
    SOCKADDR_IN receiverAddr; 
    int port = 51010; 
    char sendBuf[1024]="Hello!!!"; 
    int bufLength = 1024; 

    cout << "UDP server from book\n"; 

    //Initialize socket 
    if (WSAStartup(MAKEWORD(2,2),&wsaData) != 0) 
    { 
     cout << "Failed. Error Code : " << WSAGetLastError(); 
     exit(EXIT_FAILURE); 
    } 
    cout << "Initialised\n"; 

    if(sendingSocket = socket(AF_INET, SOCK_DGRAM, 0) == INVALID_SOCKET) 
    { 
     cout << "Could not create socket : " << WSAGetLastError(); 
    } 
    cout << "Socket created.\n"; 

    //FIll out structure of receiverAdd 
    receiverAddr.sin_family = AF_INET; 
    receiverAddr.sin_port = htons(port); 
    receiverAddr.sin_addr.s_addr = inet_addr("192.168.1.100"); 

    int test = bind(sendingSocket, (SOCKADDR*)&receiverAddr, sizeof(receiverAddr)); 
    if(test < 0) 
    { 
     cout << "Bind failed with error code : %d" << WSAGetLastError(); 
     exit(EXIT_FAILURE); 
    } 
    cout << "Bind is successful\n"; 

    while(1) 
    { 
     cout << "Sending data...\n"; 

     //Send datagram to receiver 
     if(sendto(sendingSocket, sendBuf, 1024, 0, (SOCKADDR*)&receiverAddr, sizeof(receiverAddr)) == SOCKET_ERROR) 
     { 
      cout << "sendto() failed with error code : " << WSAGetLastError(); 
      exit(EXIT_FAILURE); 
     } 
     cout << "Sent"; 
    } 

    //close socket 
    closesocket(sendingSocket); 

    WSACleanup(); 

    std::cin.get(); 

    // return 0; 
} 
+5

你忘了提问了。 – 2014-09-30 21:11:39

+0

此代码是可以格式化的。我为您解决了这个问题,但下次请在发布代码片段时[学习如何正确格式化](http://*.com/help/formatting)代码片段。 – 2014-09-30 21:15:51

+1

您还忘了查看Winsock错误10038. – EJP 2014-09-30 21:25:16

错误10038是WSAENOTSOCK: The descriptor is not a socket.

要调用socket()和分配您的SOCKET处理if语句的内部,但是您缺少足够的括号。他们应该是这样的,而不是:

if((receivingSocket = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) 

if((sendingSocket = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) 

就个人而言,我讨厌执行的if语句像这里面的分配代码。我宁愿将它们分开。它是清洁,容易出错少,没有效率较低,从编译器的角度来看:

receivingSocket = socket(AF_INET, SOCK_DGRAM, 0); 
if(receivingSocket == INVALID_SOCKET) 

sendingSocket = socket(AF_INET, SOCK_DGRAM, 0); 
if(sendingSocket == INVALID_SOCKET) 

在一个侧面说明:

  1. WSAStartup()不适合使用WSAGetLastError()错误报告,它直接返回错误代码。这在WSAStartup()文档中有明确说明。进入recvfrom()循环之前

    int err = WSAStartup(MAKEWORD(2,2),&wsaData); 
    if (err != 0) 
    { 
        cout << "Failed. Error Code : " << err; 
        exit(EXIT_FAILURE); 
    } 
    
  2. 您的UDP接收器不检查的bind()一个错误的返回值。

+1

此外,当表达式,条件等等分散在多个具有中间变量的行(和优化关闭)时,调试更容易。将复杂表达式集成到一行意味着在单步执行源代码时可能会错过或误解错误。 – 2014-09-30 21:53:09

+0

10047是'WSAEAFNOSUPPORT'。如果你没有正确地初始化'sin_family',你可以用'bind()'来得到这个错误的唯一方法。这与您选择绑定的IP无关。当接收到数据包时,你可以绑定到'INADDR_ANY',但是当发送数据包时,你不能绑定到'INADDR_ANY'。出站数据包必须具有从其发送的特定IP。 – 2014-10-01 17:43:07

+0

传递给'bind()'的'sockaddr'代表recvfrom()'监听的'LOCAL *地址和'sendto()'发送的地址。传递给sendto()和recvfrom()的'sockaddr'表示* REMOTE *地址,发送给sendto()的地址和从'recvfrom()'发送的地址。调用'bind()'时,你的命名规则有点倒退,你应该使用单独的'sockaddr'变量进行绑定和发送/接收。 – 2014-10-01 17:45:19