Client Not Acting Correctly

73 Views Asked by At

I've made two C++ files, one for a server and then a client. As you can see below in the code, I wanted to display to the client that they have been connected, and their ID as well, but when I try to connect, it clears the console correctly, but doesn't display their ID. I noticed that when I close the server and the client is still running, the client then displays the ID. Not too sure what the problem is, will be awaiting your replies! Thanks in advance, and here's the code.

Server:

// First, we'll include all the required files

#include <winsock.h>
#include <iostream>
#include <Windows.h>

using namespace std;

#pragma comment(lib, "ws2_32.lib") // Require this lib for winsock

SOCKADDR_IN addr; // This structure saves the address and ports of the server
int addrlen = sizeof(addr); // This saves the length of the address

int Counter; // Counts how many connected clients there are
SOCKET sConnect; // Socket for incoming connections
SOCKET sListen; // Socket for listening
SOCKET *Connections; // Socket for all the connections

// Init the winsock library
int InitWinSock()
{
    int Val = 0; // Make a default
    WSAData wsaData;
    WORD DllVersion = MAKEWORD(2, 1);
    Val = WSAStartup(DllVersion, &wsaData); // Initialise winsock
    return 0;
}

int main()
{
    system("color 0a"); // Change the console color to black-green
    cout << "Server Started." << endl;
    // Winsock Init
    int Val = InitWinSock();
    if(Val != 0)
    {
        // If WinSock Init fails, display an error
        MessageBoxA(NULL, "Error while starting WinSock!", "Error", MB_OK | MB_ICONERROR);
        exit(1); // Stop the procedure
    }
    Connections = (SOCKET*) calloc(64, sizeof(SOCKET));
    // Init the sockets
    sListen = socket(AF_INET, SOCK_STREAM, NULL);
    sConnect = socket(AF_INET, SOCK_STREAM, NULL);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // Server address, 127.0.0.1 is localhost
    addr.sin_port = htons(2222); // Server port
    addr.sin_family = AF_INET; // This is the type of connection
    bind(sListen, (SOCKADDR*)&addr, sizeof(addr)); // Bind server to address and port
    listen(sListen, 64); // Listen for any incoming connections
    while(true)
    {
        if(sConnect = accept(sListen, (SOCKADDR*)&addr, &addrlen))
        {
            Connections[Counter] = sConnect;
            char *Name = new char[64]; // The name of the client
            ZeroMemory(Name, 64); // We make the char empty
            sprintf(Name, "%i", Counter);
            send(Connections[Counter], Name, 64, NULL); // We send the ID to the client
            cout << "New Connection!" << endl;
            Counter ++; // Increase the amount of clients
        } // end if accept the connection
        Sleep(50); // Wait 50 milliseconds
    } // end while search for connections
}

Client:

#include <iostream>
#include <winsock.h>
#include <Windows.h>

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

using namespace std;

SOCKET sConnect; // The connection socket
SOCKADDR_IN addr; // The server adress

int Startup_WinSock()
{
    WSADATA wsaData;
    WORD DllVersion = MAKEWORD(2, 1);
    int Val = WSAStartup(DllVersion, &wsaData);
    return Val;
}

int main()
{
    system("color 0a");
    int Val = Startup_WinSock();
    if(Val != 0)
    {
        cout << "Can't Startup WinSock!" << endl; // Display error
        exit(1);
    }  
    sConnect = socket(AF_INET, SOCK_STREAM, NULL);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    addr.sin_port = htons(2222);
    addr.sin_family = AF_INET;
    cout << "Please press [ENTER]" << endl;
    cin.get();
    Val = connect(sConnect, (SOCKADDR*)&addr, sizeof(addr)); // Connect with the server
    if(Val != 0)
    {
        cout << "Can't reach the server!" << endl;
        main (); // Try again
    }
    else
    {
        system("cls"); // Clear the screen
        int ID;
        char *nID = new char[64]; // Client's ID
        char *hello = new char[64]; // Message from the server
        ZeroMemory(nID, 64);
        ZeroMemory(hello, 64);
        recv(sConnect, nID, 64, NULL); // Receive ID from server
        recv(sConnect, hello, 64, NULL); // Receive message from the server
        ID = atoi(nID); // Cast to an int
        cout << hello << endl;
        cout << "Your ID: " << ID << endl;
        cin.get();
    }
    return 0;
}
2

There are 2 best solutions below

2
On
    recv(sConnect, nID, 64, NULL); // Receive ID from server
    recv(sConnect, hello, 64, NULL); // Receive message from the server

First, you have no error checking here. You need to add error checking throughout the program or it will be impossible to troubleshoot.

Second, you have no message handling here. What happens if the first recv gets 3 bytes? You'll wind up reading the rest of the ID into the hello field.

Third, you don't send any messages. So the second recv will wait until the read attempt fails, which is when the server is terminated.

0
On

In the server you only send the id, but nothing more, meaning the client will try to receive something which haven't been sent and will block forever until it receives anything.

Oh, and you have a memory leak in the server, you allocate memory for the name (which you only clear, but doesn't actually set to anything) but you never free the memory anywhere. No need for dynamic allocation here anyway.