bugfix> c++ > 投稿

これは単純なクライアントソケットアプリケーションです。このコードを実行すると、サーバーはデータを受信すると空のバッファーを受信します。誰でも問題を見つけることができますか? コードは、ソケットを使用してデータを転送するcppで記述されます。 接続後、クライアントは「Hello im client」をサーバーに送信することになっており、サーバーはメッセージを出力しますが、何らかの問題があります。

これはサーバーコードです

#define IP "127.0.0.1"

int ConnectServer::connectTo()
{
    //----------------------
    // Initialize Winsock
    WSADATA wsaData;
    int iResult = 0;
    _ListenSocket = INVALID_SOCKET;
    sockaddr_in serverAddr;
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR) {
        wprintf(L"WSAStartup() failed with error: %d\n", iResult);
        return 1;
    }
    //----------------------
    // Create a SOCKET for listening for incoming connection requests.
    _ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (_ListenSocket == INVALID_SOCKET) {
        wprintf(L"socket function failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    //----------------------
    // The sockaddr_in structure specifies the address family,
    // IP address, and port for the socket that is being bound.
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    serverAddr.sin_port = htons(PORT);
    iResult = bind(_ListenSocket, (SOCKADDR*)& serverAddr, sizeof(serverAddr));
    if (iResult == SOCKET_ERROR) {
        wprintf(L"bind function failed with error %d\n", WSAGetLastError());
        iResult = closesocket(_ListenSocket);
        if (iResult == SOCKET_ERROR)
            wprintf(L"closesocket function failed with error %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    //----------------------
    // Listen for incoming connection requests 
    // on the created socket
    if (listen(_ListenSocket, SOMAXCONN) == SOCKET_ERROR)
    {
        wprintf(L"listen function failed with error: %d\n", WSAGetLastError());
        closesocket(_ListenSocket);
        WSACleanup();
        return 1;
    }
    // Create a SOCKET for accepting incoming requests.
    SOCKET AcceptSocket;
    sockaddr_in client;

    wprintf(L"Waiting for client to connect...\n");
    //----------------------
    // Accept the connection.
    int clientSize = sizeof(client);
    AcceptSocket = accept(_ListenSocket, (SOCKADDR*)&client, &clientSize);
    if (AcceptSocket == INVALID_SOCKET)
    {
        wprintf(L"accept failed with error: %ld\n", WSAGetLastError());
        closesocket(_ListenSocket);
        WSACleanup();
        return 1;
    }
    else
    {
        wprintf(L"Client connected.\n");
    }
    //cout << "whats happening??" << endl;
    char* buffer = "";
    iResult = recv(AcceptSocket, buffer, (int)strlen(buffer), 0);
    if (iResult == SOCKET_ERROR) {
        printf("recv function failed with error: %d\n", WSAGetLastError());
        closesocket(_server);
        WSACleanup();
        return 1;
    }
    else
    {
        printf("recieved data:\n");
        printf(buffer);
    }


    iResult = closesocket(_ListenSocket);
    if (iResult == SOCKET_ERROR) {
        wprintf(L"closesocket function failed with error %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    else
    {
        std::cout << "Client disconnected" << std::endl;
    }
    WSACleanup();
    return 0;
}

これはクライアントコードです:

int ConnectClient::connectTo()
{
    int iResult;
    WSADATA WSAData;
    SOCKET _server;
    SOCKADDR_IN addr;
    HBITMAP pic = NULL;
    WSAStartup(MAKEWORD(2, 0), &WSAData);
    _server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    addr.sin_addr.s_addr = inet_addr(IP);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    if (connect(_server, (SOCKADDR *)&addr, sizeof(addr)) == INVALID_SOCKET)
    {
        wprintf(L"connect function failed with error: %d\n", WSAGetLastError());
        system("PAUSE");
        return 1;
    }
    else{
        std::cout << "Connected to _server!" << std::endl;
        char  *Buffer = "hello I'm client";
        printf(Buffer);
        iResult = send(_server, Buffer, (int)strlen(Buffer), 0);
        if (iResult == SOCKET_ERROR) {
            printf("send failed: %d\n", WSAGetLastError());
            closesocket(_server);
            WSACleanup();
            return 1;
        }
    }
    //cout << testBuffer << endl;
    //cout << strlen(testBuffer) << endl;

    //coordinations(_server);
    iResult = closesocket(_server);
    if (iResult == SOCKET_ERROR) {
        wprintf(L"closesocket function failed with error %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    else
    {
        std::cout << "Client disconnected" << std::endl;
    }
    WSACleanup();
    std::cout << "Socket closed." << std::endl << std::endl;
    system("PAUSE");
    return 0;
}
int ConnectClient::coordinations(SOCKET server)
{
    HANDLE hStdInput, hStdOutput, hEvent;                         //WAIT_ABANDONED   = 128
    INPUT_RECORD ir[128];                                       //WAIT_OBJECT_0    = 0
    DWORD nRead;                                                //WAIT_TIMEOUT     = 258
    COORD xy;
    UINT i;
    hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    FlushConsoleInputBuffer(hStdInput);
    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);                  //Event is created non-signaled (3rd param).
    HANDLE handles[2] = { hEvent, hStdInput }; 
    //char testBuffer[1024];    
    char a;
    char b;
    //Program loops monitoring two handles.  The
    while (WaitForMultipleObjects(2, handles, FALSE, INFINITE))     //1st handle ( handles(0) ) is an event which
    {                                                           //is initially set to non-signaled.  The 2nd
        ReadConsoleInput(hStdInput, ir, 128, &nRead);                 //handle monitored by WaitForMultipleObjects()
        for (i = 0; i<nRead; i++)                                       //is the standard input handle set up to
        {                                                          //allow access to mouse/keyboard input.  As
            switch (ir[i].EventType)                                //long as neither handle is in a signaled
            {                                                      //state, WaitForMultipleObjects() will block
            case KEY_EVENT:                                       //in an efficient wait state.  If any keypress
                if (ir[i].Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) //or mouse movement occurs, WaitForMultiple
                    SetEvent(hEvent);                                //Objects will return TRUE and the input will
                else                                                //be read by ReadConsolInput().  If the [ESCAPE]
                {                                                   //key is pressed the event object represented
                    xy.X = 0; xy.Y = 0; 
                    //by hEvent will be set to a signaled state by
                    SetConsoleCursorPosition(hStdOutput, xy);         //the SetEvent() Api function.  This will be
                    printf                                           //picked up by the next WaitForMultipleObjects()
                        (    
                        //call, and the function will return FALSE and
                        "AsciiCode = %d: symbol = %c\n",                //execution will drop out of the while loop
                        ir[i].Event.KeyEvent.uChar.AsciiChar,           //and program termination will occur.
                        ir[i].Event.KeyEvent.uChar.AsciiChar
                        );     
                    a = ir[i].Event.KeyEvent.uChar.AsciiChar;
                    b = ir[i].Event.KeyEvent.uChar.AsciiChar;
                    char testBuffer[1024] = "AsciiCode = %d: symbol = %c\n", a, b;              //execution will drop out of the while loop
                                 //and program termination will occur.
                    send(server, testBuffer, strlen(testBuffer), 0);//It is important to note that if the 3rd
                }                                                   //parameter to WaitForMultipleObjects() is
                break;                                              //set to FALSE, the function will return if
            case MOUSE_EVENT:                                     //either of the handles in the HANDLE array
                xy.X = 0, xy.Y = 1;                                     //represented by handles is signaled.
                SetConsoleCursorPosition(hStdOutput, xy);
                printf
                    (
                    "%.3d\t%.3d\t%.3d",
                    ir[i].Event.MouseEvent.dwMousePosition.X,
                    ir[i].Event.MouseEvent.dwMousePosition.Y,
                    (int)ir[i].Event.MouseEvent.dwButtonState & 0x07   //mask out scroll wheel, which screws up
                    );     //output
                a = ir[i].Event.MouseEvent.dwMousePosition.X;
                b = ir[i].Event.MouseEvent.dwMousePosition.Y;
                char testBuffer[1024] = "AsciiCode = %d: symbol = %c\n", a, b;              //execution will drop out of the while loop
                //and program termination will occur.
                send(server, testBuffer, strlen(testBuffer), 0);
                break;
            }
        }
    };
    return 0;
}

回答 1 件
  • 問題はここにあります:

    char* buffer = "";
    iResult = recv(AcceptSocket, buffer, (int)strlen(buffer), 0);
    
    

    あなたは recv に言っている   buffer としてゼロバイトを読み取る  空です。

    さらに、コードにはいくつかの問題があります。次のような文字列を送信しています:

    iResult = send(_server, Buffer, (int)strlen(Buffer), 0);
    
    

    これはすべての文字を送信しますが、nullターミネーターは送信しません。ただし、サーバーコードは printf を介してコードを出力するため、ヌルターミネータが必要です。 。

    より重要な問題は、データの送信方法です。サーバーは、クライアントから送信されるデータの量を把握していないため、一度に1バイトを読み取らない限り、ヌルターミネータ(非常に非効率的)を取得するまで問題が発生します。

    これに対する通常のアプローチは、固定サイズのメッセージヘッダーを送信し、サーバーにヘッダーを読み取らせることです。ヘッダーのフィールドの1つにメッセージ本文の長さが含まれ、サーバーがヘッダーを読み取ると、メッセージ本文にメモリを割り当ててから読み取ることができます。

あなたの答え