简体   繁体   中英

sending data over socket doesn't work

I'm trying to make a chess game, through sockets. There is a server that is responsible for sending the board to the players, to get the input and response and so on.. I've tried to create a client-server (actually 2clients and server) but it doesn't work. The clients connect to the server properly, but the data that is delieved doesn't correct. For example, I send "E2-C3" from the client ; the recv result (on the server side) is always 0, or it prints garbage.

Client :

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <sys/types.h>

// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

using namespace std;


#define SERVER_IP "1.1.1.1"
#define SERVER_PORT 8888
#define BUFFER_SIZE 1024

// server side 
#define INVALID_MOVE 00
#define PLEASE_ENTER_A_MOVE 15
#define PRINT_BOARD 20
#define END_GAME 30

// client side
#define MOVE 10

int __cdecl main()
{
    WSADATA info;
    int errorDATA; // configuriation 
    int socketCreate; // create the socket - empty
    SOCKADDR_IN ClientService; // configuriation (stage 3) - data of the server.
    int connectResult;
    char sendBuf[1024], recvbuf[1024];
    int iResult;

    /*Configuration*/
    errorDATA = WSAStartup(MAKEWORD(2, 2), &info);
    if (errorDATA == INVALID_SOCKET)
    {
        printf("WSAStartup failed with error : %d\n", errorDATA);
        return -1;
    }
    /*Create empty socket*/
    socketCreate = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // creating the socket "Clean - empty"
    if (socketCreate == INVALID_SOCKET)
    {
        printf("Error number %d in creating socket!\n", WSAGetLastError());
        return -1;
    }
    printf("Creating socket SUCCEEDED!\n");

    /*Confugirate the created socket*/
    ClientService.sin_family = AF_INET;
    ClientService.sin_addr.s_addr = inet_addr(SERVER_IP); // server's ip
    ClientService.sin_port = htons(SERVER_PORT);

    /*Asking for connection*/
    connectResult = connect(socketCreate, (struct sockaddr*) &ClientService, sizeof(ClientService));

    while (1)
    {
        cout << "Please enter a move : " << endl;
        cin >> sendBuf;
        iResult = send(socketCreate, sendBuf, (int)strlen(sendBuf), 0);
        if (iResult == SOCKET_ERROR) {
            printf("send failed with error: %d\n", WSAGetLastError());
            closesocket(socketCreate);
            WSACleanup();
            return 1;
        }
        // MOVE 
        iResult = recv(socketCreate, recvbuf, strlen(recvbuf), 0);
        if (iResult > 0)
        {
            if (recvbuf[0] == '0' && recvbuf[1] == '0')
            {
                cout << "You've entered an illegal move. Please try again." << endl;
                continue;
            }
            else if (recvbuf[0] == '2' && recvbuf[1] == '0')
            {
                // print the board.
                bool keepGoing = 0;
                do
                {
                    iResult = recv(socketCreate, recvbuf, strlen(recvbuf), 0);
                    if (iResult > 0)
                    {
                        if (recvbuf[0] == '1' && recvbuf[1] == '5')
                        {
                            keepGoing = true;
                            continue;
                        }
                    }
                } while (!keepGoing);
            }
        }
        else if (iResult == 0)
            printf("Connection closed\n");
        else
            printf("recv failed with error: %d\n", WSAGetLastError());
    }


    printf("Bytes Sent: %ld\n", iResult);

    // shutdown the connection since no more data will be sent
    iResult = shutdown(socketCreate, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(socketCreate);
        WSACleanup();
        return 1;
    }


    // cleanup
    closesocket(socketCreate);
    WSACleanup();

    cin.get();
    system("pause");
    return 0;
}

server:

#include <iostream>
#include <winsock2.h>
#include <string>
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")

#define MAX_NUMBER_OF_PLAYERS 1
#define BUFFER_SIZE 1024
#define LIMIT 1

// server side 
#define INVALID_MOVE 00
#define PLEASE_ENTER_A_MOVE 15
#define PRINT_BOARD 20
#define END_GAME 30

// client side
#define MOVE 10


using namespace std;

int main()
{
    WSADATA WsaDat;
    SOCKET clientsock[2];
    int minsock = 0;
    int numsocks = MAX_NUMBER_OF_PLAYERS;
    if (WSAStartup(MAKEWORD(2, 2), &WsaDat) != 0)
    {
        std::cout << "WSA Initialization failed!\r\n";
        WSACleanup();
        system("PAUSE");
        return 0;
    }

    SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (serverSocket == INVALID_SOCKET)
    {
        std::cout << "Socket creation failed.\r\n";
        WSACleanup();
        system("PAUSE");
        return 0;
    }

    SOCKADDR_IN serverInf;
    serverInf.sin_family = AF_INET;
    serverInf.sin_addr.s_addr = INADDR_ANY;
    serverInf.sin_port = htons(8888);

    if (bind(serverSocket, (SOCKADDR*)(&serverInf), sizeof(serverInf)) == SOCKET_ERROR)
    {
        std::cout << "Unable to bind socket!\r\n";
        WSACleanup();
        system("PAUSE");
        return 0;
    }

    listen(serverSocket, 5);


    clientsock[0] = accept(serverSocket, NULL, NULL);
    cout << "Client 1 has connected." << endl;
    clientsock[1] = accept(serverSocket, NULL, NULL);
    cout << "Client 2 has connected." << endl;

    for (int i = 0; i < 2; i++)
    {
        cout << clientsock[i] << endl;
    }

    // If iMode!=0, non-blocking mode is enabled.
    u_long iMode = 1;
    ioctlsocket(serverSocket, FIONBIO, &iMode);


    char client1_buffer[BUFFER_SIZE];
    char client2_buffer[BUFFER_SIZE];
    char* clientBuffer;
    // until there isn't a mate.
    bool gameRunning = true;
    // user represents if it's user1 (0), or user2(1)
    bool user = 0;


    while (gameRunning)
    {
        if (!user)
            clientBuffer = client1_buffer;
        else
            clientBuffer = client2_buffer;

        int in = recv(clientsock[0], client1_buffer, 0, 0);
        cout << in << endl;
        if (in > 0)
        {
                // CHECKS
                // MOVE COMMAND
                // IF worked, send the board to both clients. if current user = 1 ==> do user to 0 | if the user = 0 => do user to 11
                // ELSE, send the current client (clientsock[user]) Error message and ask for a command again.
            cout << client1_buffer << endl;
                cout << " IN RECV";
                char* szMessage = "15";
                send(clientsock[0], szMessage, strlen(szMessage), 0);
        }
        else if (in == 0)
        {
            // The connection has closed.
            // REMEMBER : SAVE THE GAME SITUATION.
        }
        else
        {
            printf("recv failed: %d\n", WSAGetLastError());
            // SEND ERROR MESSAGE TO BOTH CLIENTS
        }


    }
    // Shutdown our socket
    shutdown(serverSocket, SD_SEND);

    // Close our socket entirely
    closesocket(serverSocket);

    WSACleanup();
    system("pause");
    return 0;
}

What Hans said. plus this:

int in = recv(clientsock[0], client1_buffer, 0, 0);

Your probably want to say this:

int in = recv(clientsock[0], client1_buffer, BUFFER_SIZE, 0);

Also, you are making a fundamental error that a lot of people make with sockets. You are assuming that your recv call on your server will return as many bytes was passed to the corresponding send call by the client. Fragmentation, segmentation, and other network stuff may cause you to receive only a partial amount of the message that was sent on the other node's send call. (Hence, TCP is a stream protocol as they say).

You should diligently check the return value from recv . Write your code as if the sender was only to going to send 1 byte at a time. You should put delimiters between your messages (a null char is fine) and loop on recv until you get a complete message. Otherwise, what seems to work fine on your own PC and on the local subnet will have strange bugs when deployed to the internet.

The problem is

strlen(recvbuf)

You probably mean

sizeof(recvbuf)

strlen(recvbuf) does not makes sense before you received the data, because your buffer contains just garbage, thus strlen() is just a bad random number generator. strlen(recvbuf) would make sense after you received the data if you would have made sure it was filled with 0. That not being the case, you can use the return value of recv() to find out how many bytes you received.

In the server file change

int in = recv(clientsock[0], client1_buffer, 0,0);

to

int in = recv(clientsock[0], client1_buffer, 1024,0);

change is the length of the date to be received

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM