# VBForums CodeBank > CodeBank - C++ >  C++ Simple Chat Program In a Console Window (Winsock & Multithreading)

## Jacob Roman

I made a simple chat program using a console window where you run the server in one program, and multiple clients in another, where the clients can chit chat with each other, even from different machines if you got the right port and IP address handy. You could quite possibly squeeze this into an MMO game or just about anything, Enjoy the code  :big yellow: 

Server:

C++ Code:
#include <iostream>#include <winsock2.h>#include <ws2tcpip.h>#include <string>#include <thread>#include <vector> #pragma comment (lib, "Ws2_32.lib") #define IP_ADDRESS "192.168.56.1"#define DEFAULT_PORT "3504"#define DEFAULT_BUFLEN 512 struct client_type{    int id;    SOCKET socket;}; const char OPTION_VALUE = 1;const int MAX_CLIENTS = 5; //Function Prototypesint process_client(client_type &new_client, std::vector<client_type> &client_array, std::thread &thread);int main(); int process_client(client_type &new_client, std::vector<client_type> &client_array, std::thread &thread){    std::string msg = "";    char tempmsg[DEFAULT_BUFLEN] = "";     //Session    while (1)    {        memset(tempmsg, 0, DEFAULT_BUFLEN);         if (new_client.socket != 0)        {            int iResult = recv(new_client.socket, tempmsg, DEFAULT_BUFLEN, 0);             if (iResult != SOCKET_ERROR)            {                if (strcmp("", tempmsg))                    msg = "Client #" + std::to_string(new_client.id) + ": " + tempmsg;                 std::cout << msg.c_str() << std::endl;                 //Broadcast that message to the other clients                for (int i = 0; i < MAX_CLIENTS; i++)                {                    if (client_array[i].socket != INVALID_SOCKET)                        if (new_client.id != i)                            iResult = send(client_array[i].socket, msg.c_str(), strlen(msg.c_str()), 0);                }            }            else            {                msg = "Client #" + std::to_string(new_client.id) + " Disconnected";                 std::cout << msg << std::endl;                 closesocket(new_client.socket);                closesocket(client_array[new_client.id].socket);                client_array[new_client.id].socket = INVALID_SOCKET;                 //Broadcast the disconnection message to the other clients                for (int i = 0; i < MAX_CLIENTS; i++)                {                    if (client_array[i].socket != INVALID_SOCKET)                        iResult = send(client_array[i].socket, msg.c_str(), strlen(msg.c_str()), 0);                }                 break;            }        }    } //end while     thread.detach();     return 0;} int main(){    WSADATA wsaData;    struct addrinfo hints;    struct addrinfo *server = NULL;    SOCKET server_socket = INVALID_SOCKET;    std::string msg = "";    std::vector<client_type> client(MAX_CLIENTS);    int num_clients = 0;    int temp_id = -1;    std::thread my_thread[MAX_CLIENTS];     //Initialize Winsock    std::cout << "Intializing Winsock..." << std::endl;    WSAStartup(MAKEWORD(2, 2), &wsaData);     //Setup hints    ZeroMemory(&hints, sizeof(hints));    hints.ai_family = AF_INET;    hints.ai_socktype = SOCK_STREAM;    hints.ai_protocol = IPPROTO_TCP;    hints.ai_flags = AI_PASSIVE;     //Setup Server    std::cout << "Setting up server..." << std::endl;    getaddrinfo(static_cast<LPCTSTR>(IP_ADDRESS), DEFAULT_PORT, &hints, &server);     //Create a listening socket for connecting to server    std::cout << "Creating server socket..." << std::endl;    server_socket = socket(server->ai_family, server->ai_socktype, server->ai_protocol);     //Setup socket options    setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &OPTION_VALUE, sizeof(int)); //Make it possible to re-bind to a port that was used within the last 2 minutes    setsockopt(server_socket, IPPROTO_TCP, TCP_NODELAY, &OPTION_VALUE, sizeof(int)); //Used for interactive programs     //Assign an address to the server socket.    std::cout << "Binding socket..." << std::endl;    bind(server_socket, server->ai_addr, (int)server->ai_addrlen);     //Listen for incoming connections.    std::cout << "Listening..." << std::endl;    listen(server_socket, SOMAXCONN);     //Initialize the client list    for (int i = 0; i < MAX_CLIENTS; i++)    {        client[i] = { -1, INVALID_SOCKET };    }     while (1)    {         SOCKET incoming = INVALID_SOCKET;        incoming = accept(server_socket, NULL, NULL);         if (incoming == INVALID_SOCKET) continue;         //Reset the number of clients        num_clients = -1;         //Create a temporary id for the next client        temp_id = -1;        for (int i = 0; i < MAX_CLIENTS; i++)        {            if (client[i].socket == INVALID_SOCKET && temp_id == -1)            {                client[i].socket = incoming;                client[i].id = i;                temp_id = i;            }             if (client[i].socket != INVALID_SOCKET)                num_clients++;             //std::cout << client[i].socket << std::endl;        }         if (temp_id != -1)        {            //Send the id to that client            std::cout << "Client #" << client[temp_id].id << " Accepted" << std::endl;            msg = std::to_string(client[temp_id].id);            send(client[temp_id].socket, msg.c_str(), strlen(msg.c_str()), 0);             //Create a thread process for that client            my_thread[temp_id] = std::thread(process_client, std::ref(client[temp_id]), std::ref(client), std::ref(my_thread[temp_id]));        }        else        {            msg = "Server is full";            send(incoming, msg.c_str(), strlen(msg.c_str()), 0);            std::cout << msg << std::endl;        }    } //end while      //Close listening socket    closesocket(server_socket);     //Close client socket    for (int i = 0; i < MAX_CLIENTS; i++)    {        my_thread[i].detach();        closesocket(client[i].socket);    }     //Clean up Winsock    WSACleanup();    std::cout << "Program has ended successfully" << std::endl;     system("pause");    return 0;}

Client:

C++ Code:
#include <winsock2.h>#include <ws2tcpip.h>#include <iostream>#include <string>#include <thread> using namespace std; #pragma comment (lib, "Ws2_32.lib") #define DEFAULT_BUFLEN 512            #define IP_ADDRESS "192.168.56.1"#define DEFAULT_PORT "3504" struct client_type{    SOCKET socket;    int id;    char received_message[DEFAULT_BUFLEN];}; int process_client(client_type &new_client);int main(); int process_client(client_type &new_client){    while (1)    {        memset(new_client.received_message, 0, DEFAULT_BUFLEN);         if (new_client.socket != 0)        {            int iResult = recv(new_client.socket, new_client.received_message, DEFAULT_BUFLEN, 0);             if (iResult != SOCKET_ERROR)                cout << new_client.received_message << endl;            else            {                cout << "recv() failed: " << WSAGetLastError() << endl;                break;            }        }    }     if (WSAGetLastError() == WSAECONNRESET)        cout << "The server has disconnected" << endl;     return 0;} int main(){    WSAData wsa_data;    struct addrinfo *result = NULL, *ptr = NULL, hints;    string sent_message = "";    client_type client = { INVALID_SOCKET, -1, "" };    int iResult = 0;    string message;     cout << "Starting Client...\n";     // Initialize Winsock    iResult = WSAStartup(MAKEWORD(2, 2), &wsa_data);    if (iResult != 0) {        cout << "WSAStartup() failed with error: " << iResult << endl;        return 1;    }     ZeroMemory(&hints, sizeof(hints));    hints.ai_family = AF_UNSPEC;    hints.ai_socktype = SOCK_STREAM;    hints.ai_protocol = IPPROTO_TCP;     cout << "Connecting...\n";     // Resolve the server address and port    iResult = getaddrinfo(static_cast<LPCTSTR>(IP_ADDRESS), DEFAULT_PORT, &hints, &result);    if (iResult != 0) {        cout << "getaddrinfo() failed with error: " << iResult << endl;        WSACleanup();        system("pause");        return 1;    }     // Attempt to connect to an address until one succeeds    for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {         // Create a SOCKET for connecting to server        client.socket = socket(ptr->ai_family, ptr->ai_socktype,            ptr->ai_protocol);        if (client.socket == INVALID_SOCKET) {            cout << "socket() failed with error: " << WSAGetLastError() << endl;            WSACleanup();            system("pause");            return 1;        }         // Connect to server.        iResult = connect(client.socket, ptr->ai_addr, (int)ptr->ai_addrlen);        if (iResult == SOCKET_ERROR) {            closesocket(client.socket);            client.socket = INVALID_SOCKET;            continue;        }        break;    }     freeaddrinfo(result);     if (client.socket == INVALID_SOCKET) {        cout << "Unable to connect to server!" << endl;        WSACleanup();        system("pause");        return 1;    }     cout << "Successfully Connected" << endl;     //Obtain id from server for this client;    recv(client.socket, client.received_message, DEFAULT_BUFLEN, 0);    message = client.received_message;     if (message != "Server is full")    {        client.id = atoi(client.received_message);         thread my_thread(process_client, client);         while (1)        {            getline(cin, sent_message);            iResult = send(client.socket, sent_message.c_str(), strlen(sent_message.c_str()), 0);             if (iResult <= 0)            {                cout << "send() failed: " << WSAGetLastError() << endl;                break;            }        }         //Shutdown the connection since no more data will be sent        my_thread.detach();    }    else        cout << client.received_message << endl;     cout << "Shutting down socket..." << endl;    iResult = shutdown(client.socket, SD_SEND);    if (iResult == SOCKET_ERROR) {        cout << "shutdown() failed with error: " << WSAGetLastError() << endl;        closesocket(client.socket);        WSACleanup();        system("pause");        return 1;    }     closesocket(client.socket);    WSACleanup();    system("pause");    return 0;}

----------


## thunduaga

Hi, for the following lines i get compile errors

in the server:

//Create a thread process for that client
            my_thread[temp_id] = std::thread(process_client, std::ref(client[temp_id]), std::ref(client), std::ref(my_thread[temp_id]));

in the client:

thread my_thread(process_client, client);

VS is telling me that there are no constructors matching these arguments or even this number of arguments. Could you please explain a little bit about creating these threads? is process_client the thread proc? i have some experience with win32, multithreading and thread syncronization but never networking and i dont remember using std::thread ever

----------


## tounsi8orr

i compile it with out any error, thanks for share

----------


## lafumafin

> i compile it with out any error, thanks for share



Where did you got the librarys, the header files?



```
server.cpp:2:22: fatal error: winsock2.h: Datei oder Verzeichnis nicht gefunden
compilation terminated.
client.cpp:1:22: fatal error: winsock2.h: Datei oder Verzeichnis nicht gefunden
compilation terminated.
winsock2.h:21:22: fatal error: pshpack4.h: Datei oder Verzeichnis nicht gefunden
compilation terminated.
```

----------


## tayyabayounas

> Where did you got the librarys, the header files?
> 
> 
> 
> ```
> server.cpp:2:22: fatal error: winsock2.h: Datei oder Verzeichnis nicht gefunden
> compilation terminated.
> client.cpp:1:22: fatal error: winsock2.h: Datei oder Verzeichnis nicht gefunden
> compilation terminated.
> ...


*i m using visual studio 2013 ..... plz tell me where to compile that program...can i compile it in visualstudio win32 console application or any other:confused*

----------


## Jacob Roman

Try installing the latest version of Windows SDK if it didnt come with your version of visual studio.  :Wink:

----------


## errno

Hi Jacob,

thank you so much this sample. That's great..

Best regards

----------


## petrdruker

Have the same issue... How did you solve it?

----------


## noblemaks

> Hi, for the following lines i get compile errors
> 
> in the server:
> 
> //Create a thread process for that client
>             my_thread[temp_id] = std::thread(process_client, std::ref(client[temp_id]), std::ref(client), std::ref(my_thread[temp_id]));
> 
> in the client:
> 
> ...



If you use VS 2017 the server part will compile well, but in the client you would need to change 
 thread my_thread(process_client, client);
to
 thread my_thread(process_client, ref(client));

----------

