-
Nov 27th, 2014, 01:26 AM
#1
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:
#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 Prototypes int 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; }
Last edited by Jacob Roman; Dec 5th, 2014 at 01:32 AM.
-
Jul 8th, 2015, 11:40 PM
#2
New Member
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
-
Sep 1st, 2016, 07:50 AM
#3
New Member
Re: C++ Simple Chat Program In a Console Window (Winsock & Multithreading)
i compile it with out any error, thanks for share
-
Dec 16th, 2016, 12:32 PM
#4
New Member
Re: C++ Simple Chat Program In a Console Window (Winsock & Multithreading)
 Originally Posted by tounsi8orr
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.
-
Jan 15th, 2017, 09:50 AM
#5
New Member
Re: C++ Simple Chat Program In a Console Window (Winsock & Multithreading)
 Originally Posted by lafumafin
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
-
Feb 3rd, 2017, 03:28 PM
#6
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.
-
Jun 17th, 2017, 01:05 PM
#7
New Member
Re: C++ Simple Chat Program In a Console Window (Winsock & Multithreading)
Hi Jacob,
thank you so much this sample. That's great..
Best regards
-
Sep 12th, 2017, 05:53 AM
#8
New Member
Re: C++ Simple Chat Program In a Console Window (Winsock & Multithreading)
Have the same issue... How did you solve it?
-
Aug 23rd, 2018, 03:31 AM
#9
New Member
Re: C++ Simple Chat Program In a Console Window (Winsock & Multithreading)
 Originally Posted by 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
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|