2017-11-20 5 views
0

私はクライアントであるC++のUDPソケットと一度にサーバーで作業しています。 Visual Studio 2017を使用してWindows 7で実行しています。recvfrom()関数に問題があり、「無効な引数」エラーで終了しています。私はソケットが大丈夫だと思うsockaddr_in構造体は大丈夫です、スレッドは大丈夫ですし、sendto()関数でもwhileループは大丈夫です。しかし、スレッドがのrecvfrom()関数を呼び出した後に終了し、問題がどこにあるか私は本当に知りません...winsock2:recvfrom()関数はエラー10022(無効な引数)で終了します

#include <iostream> 
#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <winsock2.h> 
#include <thread> 

#pragma comment(lib, "Ws2_32.lib") 

using namespace std; 

void printMessage(SOCKET s, SOCKADDR_IN destAddr) { 

    char message[100]; 
    int result, error; 
    int addrSize = sizeof(destAddr); 
    do { 
     printf("som v threade\n"); 
     result = recvfrom(s, message, 100, 0, (SOCKADDR*)&destAddr, &addrSize); 
     printf("%d\n", result); 

     if (result < 0) { 
      error = WSAGetLastError(); 
      printf("%d\n", error); 
     } 

     if (result > 0) 
      printf("%s", message); 

    } while (result > 0); 

} 


int main(int argc, char *argv[]) { 

    WORD dllVersion = MAKEWORD(2, 1); 
    WSADATA wsaData; 

    if (WSAStartup(dllVersion, &wsaData) != 0) { 
     printf("Winsock startup failed"); 
     exit(1); 
    } 

    const char *ip = "127.0.0.1"; 
    int dstPort = 49999; 
    int srcPort = 49999; 

    SOCKADDR_IN destaddr, srcaddr; 
    SOCKET s; 
    s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 

    if (s < 0) { 
     printf("Error creating socket"); 
     exit(1); 
    } 

    destaddr.sin_family = AF_INET; 
    destaddr.sin_addr.s_addr = inet_addr(ip); 
    destaddr.sin_port = htons(dstPort); 

    srcaddr.sin_family = AF_INET; 
    srcaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    srcaddr.sin_port = htons(srcPort); 


    bind(s, (SOCKADDR*)&srcaddr, sizeof(srcaddr)); 

    thread receiving (printMessage, s, destaddr); 
    receiving.detach(); 

    while (1) { 
     char message[100]; 

     printf("Write a message:"); 
     scanf("%s", message); 

     if (sendto(s, message, sizeof(message), 0, (SOCKADDR *) &destaddr, sizeof(destaddr)) < 0) { 
      printf("Message not sent"); 
      exit(1); 
     } 
    } 
    return 0; 
} 
+0

は、より多くのこのような何かを試してみてください。 'printf()'や他のシステムコールを呼び出す前に 'WSAGetLastError()' *を呼び出して、ループのたびに 'addrSize'を再初期化する必要があります。 – EJP

答えて

1

エラーコード10022 WSAEINVALです。 recvfrom()ドキュメントあたり:

WSAEINVAL

ソケットはbind()にバインドされていない、または未知のフラグが指定された、またはMSG_OOBが有効になってSO_OOBINLINEとのソケットに指定された、または(バイトストリームのためのスタイルソケットのみ)lenはゼロまたは負の値でした。

bind()コールが失敗していないことを確認するためにエラー処理を行っているわけではありません。または、あなたは正しいbind()関数を最初に呼び出すことさえできます。 WinSockとSTLはどちらも独自のbind()機能を持っていますが、use of using namespace std masks that factです。

また、recvfrom()に電話するたびにaddrSizeをリセットする必要があります。これは値を変更する可能性があるためです。最大バッファサイズを渡すことを期待し、バッファに実際に書き込まれたサイズを出力します。

また、適切なタイミングでWSAGetLastError()に電話をかけることもありません。失敗したWinSockコールの後にとすぐにと呼ぶ必要があります。その後、何か elseを実行してください。つまり、WSAGetLastError()を呼び出す前にprintf()に電話しないでください。エラーコードがリセットされる可能性があります。

また、recvfrom()が正常に読み取れた場合、データはNULLで終了すると見なしますが、これは保証されません。パラメータとしてresultprintf()に渡す必要があります。

そして、CスタイルのI/OとC++を混在させるべきではありません。代わりにC++スタイルのI/Oを使用してください。あなたはエラーチェック `バインド()`はありません

#include <iostream> 
#include <string> 
#include <thread> 
#include <winsock2.h> 

#pragma comment(lib, "Ws2_32.lib") 

void printMessage(SOCKET s) 
{ 
    char message[100]; 
    int result, error, addrSize; 
    SOCKADDR_IN clientaddr; 

    do { 
     std::cout << "som v threade" << std::endl; 
     addrSize = sizeof(clientaddr); 
     result = recvfrom(s, message, 100, 0, (SOCKADDR*)&clientaddr, &addrSize); 
     if (result == SOCKET_ERROR) { 
      error = WSAGetLastError(); 
      std::cout << "Receive failed. Error: " << error << std::endl; 
      continue; 
     } 
     std::cout << "Received " << result << " byte(s) from " << inet_ntoa(clientaddr.sin_addr) << ":" << ntohs(clientaddr.sin_port) << std::endl; 
     if (result > 0) { 
      std::cout.write(message, result); 
      std::cout << std::endl; 
     } 
    } 
    while (result > 0); 
} 

int main(int argc, char *argv[]) { 
    WORD dllVersion = MAKEWORD(2, 1); 
    WSADATA wsaData;  
    int result, error; 

    result = WSAStartup(dllVersion, &wsaData); 
    if (result != 0) { 
     std::cout << "Winsock startup failed. Error: " << result << std::endl; 
     exit(1); 
    } 

    SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 
    if (s == INVALID_SOCKET) { 
     error = WSAGetLastError(); 
     std::cout << "Socket creation failed. Error: " << error << std::endl; 
     exit(1); 
    } 

    const char *ip = "127.0.0.1"; 
    unsigned short dstPort = 49999; 
    unsigned short srcPort = 49999; 

    SOCKADDR_IN destaddr = {}; 
    SOCKADDR_IN srcaddr = {}; 

    destaddr.sin_family = AF_INET; 
    destaddr.sin_addr.s_addr = inet_addr(ip); 
    destaddr.sin_port = htons(dstPort); 

    srcaddr.sin_family = AF_INET; 
    srcaddr.sin_addr.s_addr = INADDR_ANY; 
    srcaddr.sin_port = htons(srcPort); 

    result = ::bind(s, (SOCKADDR*)&srcaddr, sizeof(srcaddr)); 
    if (result == SOCKET_ERROR) { 
     error = WSAGetLastError(); 
     std::cout << "Socket bind failed. Error: " << error << std::endl; 
     exit(1); 
    } 

    std::thread receiving(printMessage, s); 
    receiving.detach(); 

    std::string message; 
    do { 
     std::cout << "Write a message: "; 
     std::getline(std::cin, message); 
     result = sendto(s, message.c_str(), message.size(), 0, (SOCKADDR *) &destaddr, sizeof(destaddr)); 
     if (result == SOCKET_ERROR) { 
      error = WSAGetLastError(); 
      std::cout << "Message not sent. Error: " << error << std::endl; 
      exit(1); 
     } 
    } 
    while (true); 

    return 0; 
} 
関連する問題