Results 1 to 9 of 9

Thread: C++ Simple Chat Program In a Console Window (Winsock & Multithreading)

  1. #1

    Thread Starter
    College Grad!!! Jacob Roman's Avatar
    Join Date
    Aug 2004
    Location
    Miami Beach, FL
    Posts
    5,333

    C++ Simple Chat Program In a Console Window (Winsock & Multithreading)

    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

    Server:
    C++ Code:
    1. #include <iostream>
    2. #include <winsock2.h>
    3. #include <ws2tcpip.h>
    4. #include <string>
    5. #include <thread>
    6. #include <vector>
    7.  
    8. #pragma comment (lib, "Ws2_32.lib")
    9.  
    10. #define IP_ADDRESS "192.168.56.1"
    11. #define DEFAULT_PORT "3504"
    12. #define DEFAULT_BUFLEN 512
    13.  
    14. struct client_type
    15. {
    16.     int id;
    17.     SOCKET socket;
    18. };
    19.  
    20. const char OPTION_VALUE = 1;
    21. const int MAX_CLIENTS = 5;
    22.  
    23. //Function Prototypes
    24. int process_client(client_type &new_client, std::vector<client_type> &client_array, std::thread &thread);
    25. int main();
    26.  
    27. int process_client(client_type &new_client, std::vector<client_type> &client_array, std::thread &thread)
    28. {
    29.     std::string msg = "";
    30.     char tempmsg[DEFAULT_BUFLEN] = "";
    31.  
    32.     //Session
    33.     while (1)
    34.     {
    35.         memset(tempmsg, 0, DEFAULT_BUFLEN);
    36.  
    37.         if (new_client.socket != 0)
    38.         {
    39.             int iResult = recv(new_client.socket, tempmsg, DEFAULT_BUFLEN, 0);
    40.  
    41.             if (iResult != SOCKET_ERROR)
    42.             {
    43.                 if (strcmp("", tempmsg))
    44.                     msg = "Client #" + std::to_string(new_client.id) + ": " + tempmsg;
    45.  
    46.                 std::cout << msg.c_str() << std::endl;
    47.  
    48.                 //Broadcast that message to the other clients
    49.                 for (int i = 0; i < MAX_CLIENTS; i++)
    50.                 {
    51.                     if (client_array[i].socket != INVALID_SOCKET)
    52.                         if (new_client.id != i)
    53.                             iResult = send(client_array[i].socket, msg.c_str(), strlen(msg.c_str()), 0);
    54.                 }
    55.             }
    56.             else
    57.             {
    58.                 msg = "Client #" + std::to_string(new_client.id) + " Disconnected";
    59.  
    60.                 std::cout << msg << std::endl;
    61.  
    62.                 closesocket(new_client.socket);
    63.                 closesocket(client_array[new_client.id].socket);
    64.                 client_array[new_client.id].socket = INVALID_SOCKET;
    65.  
    66.                 //Broadcast the disconnection message to the other clients
    67.                 for (int i = 0; i < MAX_CLIENTS; i++)
    68.                 {
    69.                     if (client_array[i].socket != INVALID_SOCKET)
    70.                         iResult = send(client_array[i].socket, msg.c_str(), strlen(msg.c_str()), 0);
    71.                 }
    72.  
    73.                 break;
    74.             }
    75.         }
    76.     } //end while
    77.  
    78.     thread.detach();
    79.  
    80.     return 0;
    81. }
    82.  
    83. int main()
    84. {
    85.     WSADATA wsaData;
    86.     struct addrinfo hints;
    87.     struct addrinfo *server = NULL;
    88.     SOCKET server_socket = INVALID_SOCKET;
    89.     std::string msg = "";
    90.     std::vector<client_type> client(MAX_CLIENTS);
    91.     int num_clients = 0;
    92.     int temp_id = -1;
    93.     std::thread my_thread[MAX_CLIENTS];
    94.  
    95.     //Initialize Winsock
    96.     std::cout << "Intializing Winsock..." << std::endl;
    97.     WSAStartup(MAKEWORD(2, 2), &wsaData);
    98.  
    99.     //Setup hints
    100.     ZeroMemory(&hints, sizeof(hints));
    101.     hints.ai_family = AF_INET;
    102.     hints.ai_socktype = SOCK_STREAM;
    103.     hints.ai_protocol = IPPROTO_TCP;
    104.     hints.ai_flags = AI_PASSIVE;
    105.  
    106.     //Setup Server
    107.     std::cout << "Setting up server..." << std::endl;
    108.     getaddrinfo(static_cast<LPCTSTR>(IP_ADDRESS), DEFAULT_PORT, &hints, &server);
    109.  
    110.     //Create a listening socket for connecting to server
    111.     std::cout << "Creating server socket..." << std::endl;
    112.     server_socket = socket(server->ai_family, server->ai_socktype, server->ai_protocol);
    113.  
    114.     //Setup socket options
    115.     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
    116.     setsockopt(server_socket, IPPROTO_TCP, TCP_NODELAY, &OPTION_VALUE, sizeof(int)); //Used for interactive programs
    117.  
    118.     //Assign an address to the server socket.
    119.     std::cout << "Binding socket..." << std::endl;
    120.     bind(server_socket, server->ai_addr, (int)server->ai_addrlen);
    121.  
    122.     //Listen for incoming connections.
    123.     std::cout << "Listening..." << std::endl;
    124.     listen(server_socket, SOMAXCONN);
    125.  
    126.     //Initialize the client list
    127.     for (int i = 0; i < MAX_CLIENTS; i++)
    128.     {
    129.         client[i] = { -1, INVALID_SOCKET };
    130.     }
    131.  
    132.     while (1)
    133.     {
    134.  
    135.         SOCKET incoming = INVALID_SOCKET;
    136.         incoming = accept(server_socket, NULL, NULL);
    137.  
    138.         if (incoming == INVALID_SOCKET) continue;
    139.  
    140.         //Reset the number of clients
    141.         num_clients = -1;
    142.  
    143.         //Create a temporary id for the next client
    144.         temp_id = -1;
    145.         for (int i = 0; i < MAX_CLIENTS; i++)
    146.         {
    147.             if (client[i].socket == INVALID_SOCKET && temp_id == -1)
    148.             {
    149.                 client[i].socket = incoming;
    150.                 client[i].id = i;
    151.                 temp_id = i;
    152.             }
    153.  
    154.             if (client[i].socket != INVALID_SOCKET)
    155.                 num_clients++;
    156.  
    157.             //std::cout << client[i].socket << std::endl;
    158.         }
    159.  
    160.         if (temp_id != -1)
    161.         {
    162.             //Send the id to that client
    163.             std::cout << "Client #" << client[temp_id].id << " Accepted" << std::endl;
    164.             msg = std::to_string(client[temp_id].id);
    165.             send(client[temp_id].socket, msg.c_str(), strlen(msg.c_str()), 0);
    166.  
    167.             //Create a thread process for that client
    168.             my_thread[temp_id] = std::thread(process_client, std::ref(client[temp_id]), std::ref(client), std::ref(my_thread[temp_id]));
    169.         }
    170.         else
    171.         {
    172.             msg = "Server is full";
    173.             send(incoming, msg.c_str(), strlen(msg.c_str()), 0);
    174.             std::cout << msg << std::endl;
    175.         }
    176.     } //end while
    177.  
    178.  
    179.     //Close listening socket
    180.     closesocket(server_socket);
    181.  
    182.     //Close client socket
    183.     for (int i = 0; i < MAX_CLIENTS; i++)
    184.     {
    185.         my_thread[i].detach();
    186.         closesocket(client[i].socket);
    187.     }
    188.  
    189.     //Clean up Winsock
    190.     WSACleanup();
    191.     std::cout << "Program has ended successfully" << std::endl;
    192.  
    193.     system("pause");
    194.     return 0;
    195. }

    Client:
    C++ Code:
    1. #include <winsock2.h>
    2. #include <ws2tcpip.h>
    3. #include <iostream>
    4. #include <string>
    5. #include <thread>
    6.  
    7. using namespace std;
    8.  
    9. #pragma comment (lib, "Ws2_32.lib")
    10.  
    11. #define DEFAULT_BUFLEN 512            
    12. #define IP_ADDRESS "192.168.56.1"
    13. #define DEFAULT_PORT "3504"
    14.  
    15. struct client_type
    16. {
    17.     SOCKET socket;
    18.     int id;
    19.     char received_message[DEFAULT_BUFLEN];
    20. };
    21.  
    22. int process_client(client_type &new_client);
    23. int main();
    24.  
    25. int process_client(client_type &new_client)
    26. {
    27.     while (1)
    28.     {
    29.         memset(new_client.received_message, 0, DEFAULT_BUFLEN);
    30.  
    31.         if (new_client.socket != 0)
    32.         {
    33.             int iResult = recv(new_client.socket, new_client.received_message, DEFAULT_BUFLEN, 0);
    34.  
    35.             if (iResult != SOCKET_ERROR)
    36.                 cout << new_client.received_message << endl;
    37.             else
    38.             {
    39.                 cout << "recv() failed: " << WSAGetLastError() << endl;
    40.                 break;
    41.             }
    42.         }
    43.     }
    44.  
    45.     if (WSAGetLastError() == WSAECONNRESET)
    46.         cout << "The server has disconnected" << endl;
    47.  
    48.     return 0;
    49. }
    50.  
    51. int main()
    52. {
    53.     WSAData wsa_data;
    54.     struct addrinfo *result = NULL, *ptr = NULL, hints;
    55.     string sent_message = "";
    56.     client_type client = { INVALID_SOCKET, -1, "" };
    57.     int iResult = 0;
    58.     string message;
    59.  
    60.     cout << "Starting Client...\n";
    61.  
    62.     // Initialize Winsock
    63.     iResult = WSAStartup(MAKEWORD(2, 2), &wsa_data);
    64.     if (iResult != 0) {
    65.         cout << "WSAStartup() failed with error: " << iResult << endl;
    66.         return 1;
    67.     }
    68.  
    69.     ZeroMemory(&hints, sizeof(hints));
    70.     hints.ai_family = AF_UNSPEC;
    71.     hints.ai_socktype = SOCK_STREAM;
    72.     hints.ai_protocol = IPPROTO_TCP;
    73.  
    74.     cout << "Connecting...\n";
    75.  
    76.     // Resolve the server address and port
    77.     iResult = getaddrinfo(static_cast<LPCTSTR>(IP_ADDRESS), DEFAULT_PORT, &hints, &result);
    78.     if (iResult != 0) {
    79.         cout << "getaddrinfo() failed with error: " << iResult << endl;
    80.         WSACleanup();
    81.         system("pause");
    82.         return 1;
    83.     }
    84.  
    85.     // Attempt to connect to an address until one succeeds
    86.     for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
    87.  
    88.         // Create a SOCKET for connecting to server
    89.         client.socket = socket(ptr->ai_family, ptr->ai_socktype,
    90.             ptr->ai_protocol);
    91.         if (client.socket == INVALID_SOCKET) {
    92.             cout << "socket() failed with error: " << WSAGetLastError() << endl;
    93.             WSACleanup();
    94.             system("pause");
    95.             return 1;
    96.         }
    97.  
    98.         // Connect to server.
    99.         iResult = connect(client.socket, ptr->ai_addr, (int)ptr->ai_addrlen);
    100.         if (iResult == SOCKET_ERROR) {
    101.             closesocket(client.socket);
    102.             client.socket = INVALID_SOCKET;
    103.             continue;
    104.         }
    105.         break;
    106.     }
    107.  
    108.     freeaddrinfo(result);
    109.  
    110.     if (client.socket == INVALID_SOCKET) {
    111.         cout << "Unable to connect to server!" << endl;
    112.         WSACleanup();
    113.         system("pause");
    114.         return 1;
    115.     }
    116.  
    117.     cout << "Successfully Connected" << endl;
    118.  
    119.     //Obtain id from server for this client;
    120.     recv(client.socket, client.received_message, DEFAULT_BUFLEN, 0);
    121.     message = client.received_message;
    122.  
    123.     if (message != "Server is full")
    124.     {
    125.         client.id = atoi(client.received_message);
    126.  
    127.         thread my_thread(process_client, client);
    128.  
    129.         while (1)
    130.         {
    131.             getline(cin, sent_message);
    132.             iResult = send(client.socket, sent_message.c_str(), strlen(sent_message.c_str()), 0);
    133.  
    134.             if (iResult <= 0)
    135.             {
    136.                 cout << "send() failed: " << WSAGetLastError() << endl;
    137.                 break;
    138.             }
    139.         }
    140.  
    141.         //Shutdown the connection since no more data will be sent
    142.         my_thread.detach();
    143.     }
    144.     else
    145.         cout << client.received_message << endl;
    146.  
    147.     cout << "Shutting down socket..." << endl;
    148.     iResult = shutdown(client.socket, SD_SEND);
    149.     if (iResult == SOCKET_ERROR) {
    150.         cout << "shutdown() failed with error: " << WSAGetLastError() << endl;
    151.         closesocket(client.socket);
    152.         WSACleanup();
    153.         system("pause");
    154.         return 1;
    155.     }
    156.  
    157.     closesocket(client.socket);
    158.     WSACleanup();
    159.     system("pause");
    160.     return 0;
    161. }

  2. #2
    New Member
    Join Date
    Jul 2015
    Posts
    1

    Re: C++ Simple Chat Program In a Console Window (Winsock & Multithreading)

    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

  3. #3

    Re: C++ Simple Chat Program In a Console Window (Winsock & Multithreading)

    i compile it with out any error, thanks for share

  4. #4
    New Member
    Join Date
    Dec 2016
    Posts
    1

    Re: C++ Simple Chat Program In a Console Window (Winsock & Multithreading)

    Quote Originally Posted by tounsi8orr View Post
    i compile it with out any error, thanks for share

    Where did you got the librarys, the header files?

    Code:
    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.

  5. #5
    New Member
    Join Date
    Jan 2017
    Posts
    1

    Question Re: C++ Simple Chat Program In a Console Window (Winsock & Multithreading)

    Quote Originally Posted by lafumafin View Post
    Where did you got the librarys, the header files?

    Code:
    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.
    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

  6. #6

    Thread Starter
    College Grad!!! Jacob Roman's Avatar
    Join Date
    Aug 2004
    Location
    Miami Beach, FL
    Posts
    5,333

    Re: C++ Simple Chat Program In a Console Window (Winsock & Multithreading)

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

  7. #7
    New Member
    Join Date
    Jun 2017
    Posts
    1

    Re: C++ Simple Chat Program In a Console Window (Winsock & Multithreading)

    Hi Jacob,

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

    Best regards

  8. #8

    Re: C++ Simple Chat Program In a Console Window (Winsock & Multithreading)

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

  9. #9
    New Member
    Join Date
    Aug 2018
    Posts
    1

    Re: C++ Simple Chat Program In a Console Window (Winsock & Multithreading)

    Quote Originally Posted by thunduaga View Post
    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

    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));

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width