Socket programming
It is a small prerequisite of reading my blogs on Pattern-Oriented Software Architecture volume-2 book. If you want to read this book, It is even required.
In this blog, I have explained three different scenarios of client-server communication over TCP-IP. I have used windows socket to implement the code.
My intention here is not to discuss the theory of socket programming. I am just giving you a very basic implementation so that you can use this code to learn distributed patterns on a client-server based system on socket programming.
If you are interested in reading the basic theory of socket programming before go ahead, please read this link.
ConnectSocket.cpp
In this blog, I have explained three different scenarios of client-server communication over TCP-IP. I have used windows socket to implement the code.
My intention here is not to discuss the theory of socket programming. I am just giving you a very basic implementation so that you can use this code to learn distributed patterns on a client-server based system on socket programming.
If you are interested in reading the basic theory of socket programming before go ahead, please read this link.
- You are sending and receiving one massage at a time.
- It's the first and most straightforward example where you send a small packet request to the server and wait for its response.
- You are sending large files from client to server.
- In case I have MB or GB of data to send from the client to the server. Here I am sending data from the client-side and writing it down to a new file created at the server end.
- Multiple clients send messages to the server.
- It's an interesting one, as there are multiple clients. I am sending request individually at the same time. I have used C++11 multithreading to implement it.
Please click on the image to see the zoom view. |
Please click on the image to see the zoom view. |
Please click on the image to see the zoom view. |
Implementation
Let's start with the server.
SocketAcceptor.h
This class is responsible for setting up the server socket connection.
This class is responsible for setting up the server socket connection.
/*************************************************************************************************** // Author: Kunjesh Singh Baghel // Web-page: https://sites.google.com/site/kunjeshsinghbaghel/ ***************************************************************************************************/ #ifndef _SOCKET_ACCEPTOR_ #define _SOCKET_ACCEPTOR_ #pragma once #include <winsock2.h> #include <memory> #include <thread> #include <atomic> #include "Socket.h" #include "IMessage.h" using namespace IO_MSG; #define MAX_CLIENT 20 namespace SERVER_SOCKET { class SocketAcceptor { private: WSADATA windowsSocketsData; SOCKET serverSocket; volatile SOCKET clientSocket; SOCKADDR_IN serverAddress; SOCKADDR_IN clientAddress; USHORT sPortNumber; bool isConnectionSuccess; std::shared_ptr<Socket> sConnect; //__________________________For multi-client connection. std::atomic<int> clientIndex; bool bStopPooling; std::thread tClients[MAX_CLIENT]; bool Setup(); bool Bind(); bool Listen(); bool AcceptCleintConnection(); public: /* Constructor */ SocketAcceptor(); /* destructor */ ~SocketAcceptor(); bool inline IsServerSocketCreated() { return isConnectionSuccess; } bool Accept(); std::shared_ptr<Socket> GetSocket(); //__________________________For multi-client connection. /*! * Description : This method will create one thread per client connection. */ bool MultiClientAccept(); void ClearAcceptThread(); }; } #endif // !_SOCKET_ACCEPTOR_
SocketAcceptor.cpp
/*************************************************************************************************** // Author: Kunjesh Singh Baghel // Web-page: https://sites.google.com/site/kunjeshsinghbaghel/ ***************************************************************************************************/ #ifndef _SOCKET_ACCEPTOR_ #pragma once // WinAPI indicates to the linker that the Ws2_32.lib file is needed. #pragma comment(lib,"ws2_32.lib") #include "SocketAcceptor.h" #include "Log.h" #include "GlobalFactory.h" #include <windows.h> #include <ws2tcpip.h> #include <iphlpapi.h> #include<iostream> using namespace SESSION; using namespace CONFIGURATION_MANAGER; namespace SERVER_SOCKET { //__________________________For multi-client connection. Queue <shared_ptr<IMessage > > Socket::clientRequests; SocketAcceptor::SocketAcceptor(): serverSocket(INVALID_SOCKET), clientSocket(INVALID_SOCKET), sPortNumber(0), isConnectionSuccess(false), sConnect(nullptr), clientIndex(0), bStopPooling(false) { LOG_IT(LOG::SETUP_INFO, "SocketAcceptor Constructor called"); sPortNumber = std::stoi(FactoryInstance::GetGlobalFactory()->GetConfigurationManager()->GetValue("Port_number", VALUE)); LOG_IT(LOG::SETUP_INFO, "Port number - %d", sPortNumber); if (!Setup()) return; if (!Bind()) return; if (!Listen()) return; sConnect = std::make_shared<Socket>(); isConnectionSuccess = true; } SocketAcceptor::~SocketAcceptor() { LOG_IT(LOG::SETUP_INFO, "Cleanup process : SocketAcceptor getting Closed"); shutdown(serverSocket, SD_SEND); // Shutdown our socket closesocket(serverSocket); // Close our socket entirely LOG_IT(LOG::SETUP_INFO, "~SocketAcceptor Shutting down the socket"); shutdown(clientSocket, SD_SEND); LOG_IT(LOG::SETUP_INFO, "~SocketAcceptor Shutting server socket"); WSACleanup(); } bool SocketAcceptor::Setup() { LOG_IT(LOG::SETUP_INFO, "Starting the setup"); int rVal = WSAStartup(MAKEWORD(2, 0), &windowsSocketsData); if (rVal != 0) { LOG_IT(LOG::ERROR_MSG, "WSAStartup failed with error %d " , rVal); return false; } serverSocket = socket(AF_INET, SOCK_STREAM, 0); if (serverSocket == INVALID_SOCKET) { LOG_IT(LOG::ERROR_MSG, "Not able to create server socket, error code is - %d ", WSAGetLastError()); return false; } serverAddress.sin_addr.s_addr = INADDR_ANY; serverAddress.sin_family = AF_INET; serverAddress.sin_port = htons(sPortNumber); LOG_IT(LOG::SETUP_INFO, "Server Socket is created ..."); return true; } bool SocketAcceptor::Bind() { LOG_IT(LOG::SETUP_INFO, "Binding initiated ..."); // if we don't use :: for bind it sees some other bind and gets error, to call global bind we need scoped resolution operator. auto iResult = ::bind(serverSocket, (SOCKADDR*)& serverAddress, sizeof(serverAddress)); if (iResult == SOCKET_ERROR) { LOG_IT(LOG::ERROR_MSG, "bind failed with error - %d ", WSAGetLastError()); return false; } LOG_IT(LOG::SETUP_INFO, "Binding Completed ..."); return true; } bool SocketAcceptor::Listen() { LOG_IT(LOG::SETUP_INFO, "Server starts listening ..."); if (listen(serverSocket, 10) == SOCKET_ERROR) { LOG_IT(LOG::ERROR_MSG, "Listen failed with error - %d ", WSAGetLastError()); return false; } return true; } void SocketAcceptor::ClearAcceptThread() { while (clientIndex >= 0) { if (tClients[clientIndex].joinable()) { tClients[clientIndex].join(); } --clientIndex; } } bool SocketAcceptor::MultiClientAccept() { while (true) { if (bStopPooling) { break; } if (!AcceptCleintConnection()) return false; tClients[clientIndex] = std::thread(Socket::MultiClientReceiveShortMsg, sConnect.get(), clientSocket); ++clientIndex; if (clientIndex >= MAX_CLIENT - 2) { ClearAcceptThread(); } } if(clientIndex > 0) // for clean up. ClearAcceptThread(); return true; } bool SocketAcceptor::Accept() { if (!AcceptCleintConnection()) return false; sConnect->SetConnectionHandle(clientSocket); return true; } std::shared_ptr<Socket> SocketAcceptor::GetSocket() { return sConnect; } bool SocketAcceptor::AcceptCleintConnection() { int clientAddrSize = sizeof(clientAddress); clientSocket = accept(serverSocket, (SOCKADDR*)& clientAddress, &clientAddrSize); LOG_IT(LOG::SETUP_INFO, "accepted from client socket - %d", serverSocket); if (clientSocket == INVALID_SOCKET) { LOG_IT(LOG::ERROR_MSG, "accept failed: %d ", WSAGetLastError()); return false; } return true; } } #endif // !_SOCKET_ACCEPTOR_
Socket.h
Once the connection is established. Socket class will send/receive the massages.
Once the connection is established. Socket class will send/receive the massages.
/*************************************************************************************************** // Author: Kunjesh Singh Baghel // Web-page: https://sites.google.com/site/kunjeshsinghbaghel/ ***************************************************************************************************/ #ifndef _SOCKET_H_ #define _SOCKET_H_ // The WIN32_LEAN_AND_MEAN macro prevents the Winsock.h from being included by the Windows.h header #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #pragma once #include <winsock2.h> #include "Queue.h" #include "IMessage.h" using namespace IO_MSG; using namespace Thread; namespace SERVER_SOCKET { class Socket { private: SOCKET clientSocket; USHORT sBufferLen; bool Receive(char* buffer, int& byteReceived, SOCKET client, std::shared_ptr<IMessage> pMsg = nullptr); size_t Send(const char* msg, SOCKET client); //__________________________For multi-client connection. static Queue <shared_ptr<IMessage > > clientRequests; public: /* Default constructor */ Socket(); /* Destructor */ ~Socket(); void SetConnectionHandle(SOCKET clientSocket); SOCKET GetConnectionHandle(); bool ReceiveAndLogMessage(); bool ReceiveShortMsg(std::shared_ptr<IMessage> pMsg = nullptr); size_t SendToClient(const char* msg, SOCKET client = 0); //__________________________For multi-client connection. static bool MultiClientReceiveShortMsg(void *pThis, SOCKET client); static Queue <shared_ptr<IMessage > >& GetClientRequests(); }; } #endif // !_SOCKET_H_
Socket.cpp
Now come to the client
/*************************************************************************************************** // Author: Kunjesh Singh Baghel // Web-page: https://sites.google.com/site/kunjeshsinghbaghel/ ***************************************************************************************************/ #include "Socket.h" #include "Log.h" #include "GlobalFactory.h" #include "WriteOnlyFile.h" using namespace SESSION; using namespace CONFIGURATION_MANAGER; using namespace FILE_IO; char Buffer[512]; namespace SERVER_SOCKET { Socket::Socket() : clientSocket(INVALID_SOCKET) { LOG_IT(LOG::SETUP_INFO, "Construction process : server Socket is getting created"); sBufferLen = std::stoi(FactoryInstance::GetGlobalFactory()->GetConfigurationManager()->GetValue("Buffer_size", VALUE)); } Socket::~Socket() { LOG_IT(LOG::SETUP_INFO, "Cleanup process : server Socket is getting closed"); } void Socket::SetConnectionHandle(SOCKET clientSocket) { this->clientSocket = clientSocket; } SOCKET Socket::GetConnectionHandle() { return clientSocket; } bool Socket::ReceiveShortMsg(std::shared_ptr<IMessage> pMsg) { int byteReceived; if (Receive(Buffer, byteReceived, clientSocket, pMsg)) { LOG_IT(LOG::INFO, "Total bytes received from the client is - : %d", byteReceived); return true; } return false; } bool Socket::MultiClientReceiveShortMsg(void *pThis, SOCKET client) { Socket* thisPtr = static_cast<Socket*>(pThis); char Buff[512]; // creating local buffer. This will help in multi-threaded environment. int byteReceived = 0; do { shared_ptr<IMessage > pMsg = make_shared<Message>(); if (!thisPtr->Receive(Buff, byteReceived, client, pMsg)) return false; clientRequests.Insert(pMsg); } while (byteReceived > 0); LOG_IT(LOG::INFO, "Total bytes received from the client is - : %d", byteReceived); return true; } bool Socket::ReceiveAndLogMessage() { LOG_IT(LOG::SETUP_INFO, "Receiving the client data - "); size_t byteReceived = 0; int rValue = 0; //______________________________________ Large msg need to be dumped at file. std::string filePath = FactoryInstance::GetGlobalFactory()->GetFileName(); filePath = filePath.substr(0, filePath.find_last_of("\\")); filePath = filePath + "\\" + to_string(clientSocket) + ".log"; std::unique_ptr<IWriteOnlyFile> pFile = std::make_unique<WriteOnlyFile>(filePath, DELETE_OLD_CONTENT_ON_EVERY_RELOAD, false); do { Receive(Buffer, rValue, clientSocket); pFile->Write(Buffer); } while (rValue > 0); LOG_IT(LOG::INFO, "Receive message in bytes - %d", byteReceived); return true; } bool Socket::Receive(char* buffer, int& byteReceived, SOCKET client, std::shared_ptr<IMessage> pMsg) { memset(buffer, 0, sizeof(buffer)); byteReceived = recv(client, buffer, 512, 0); if (byteReceived > 0) { LOG_IT(LOG::INFO, "Message from the client %d is - : %s", client, buffer); if (pMsg != nullptr) // Setting the info into the IMessage buffer class. { pMsg->SetMsg(string(buffer)); pMsg->SetFromSocket(to_string(client)); } } else if (byteReceived == 0) { LOG_IT(LOG::ERROR_MSG, " Connection is closed "); return false; } else { LOG_IT(LOG::ERROR_MSG, "recv failed with error code - : %d", WSAGetLastError()); return false; } return true; } size_t Socket::Send(const char* msg, SOCKET client) { size_t byteSend = 0; LOG_IT(LOG::SETUP_INFO, " Sending data back to the client %d", client); memset(Buffer, 0, sizeof(Buffer)); std::memcpy(Buffer, msg, 512); byteSend = send(client, Buffer, sizeof(Buffer), 0); if (byteSend == SOCKET_ERROR) { LOG_IT(LOG::ERROR_MSG, "send failed with error: %d ", WSAGetLastError()); } return byteSend; } size_t Socket::SendToClient(const char *msg, SOCKET client) { if (client != 0) { return Send(msg, client); } else { return Send(msg, clientSocket); } } Queue <shared_ptr<IMessage > >& Socket::GetClientRequests() { return clientRequests; } }
Now come to the client
ConnectSocket.h
This class is responsible for setting up the client socket.
This class is responsible for setting up the client socket.
/*************************************************************************************************** // Author: Kunjesh Singh Baghel // Web-page: https://sites.google.com/site/kunjeshsinghbaghel/ ***************************************************************************************************/ #ifndef _CONNECT_SOCKET_ #define _CONNECT_SOCKET_ #endif // !_CONNECT_SOCKET_ #include <string> #include <memory> #include "SendAndReceiveMessages.h" namespace CLIENT_SOCKET { class ConnectToServer { private: WSADATA windowsSocketsData; SOCKET serverSocket; SOCKADDR_IN serverAddress; std::string serverIpAddress; USHORT sPortNumber; bool isConnectionSuccess; std::shared_ptr<SendAndReceive> pSendMsg; bool Setup(); public: /* Default constructor */ ConnectToServer(); /* Destructor */ ~ConnectToServer(); bool IsConnected(); std::shared_ptr<SendAndReceive> GetSendAndReceive(); bool Connect(); }; } #pragma once
ConnectSocket.cpp
/*************************************************************************************************** // Author: Kunjesh Singh Baghel // Web-page: https://sites.google.com/site/kunjeshsinghbaghel/ ***************************************************************************************************/ #pragma warning(disable:4996) #pragma comment(lib,"ws2_32.lib") // WinAPI indicates to the linker that the Ws2_32.lib file is needed. #include <ws2tcpip.h> #include <iphlpapi.h> #include <windows.h> #include "ConnectSocket.h" #include "GlobalFactory.h" #include "Log.h" using namespace SESSION; using namespace CONFIGURATION_MANAGER; namespace CLIENT_SOCKET { ConnectToServer::ConnectToServer() : isConnectionSuccess(false), pSendMsg(nullptr) { serverIpAddress = FactoryInstance::GetGlobalFactory()->GetConfigurationManager()->GetValue("IP_Address", VALUE); sPortNumber = std::stoi(FactoryInstance::GetGlobalFactory()->GetConfigurationManager()->GetValue("Port_number", VALUE)); if (!Setup()) { LOG_IT(LOG::ERROR_MSG, "ConnectToServer Setup failed "); return; } if (!Connect()) { LOG_IT(LOG::ERROR_MSG, "ConnectToServer Connect failed "); return; } pSendMsg.reset(new SendAndReceive(serverSocket)); isConnectionSuccess = true; } ConnectToServer::~ConnectToServer() { LOG_IT(LOG::SETUP_INFO, "Cleanup process : ConnectToServer client socket is getting cleaned up"); } bool ConnectToServer::IsConnected() { return isConnectionSuccess; } std::shared_ptr<SendAndReceive> ConnectToServer::GetSendAndReceive() { return pSendMsg; } bool ConnectToServer::Setup() { int rVal = WSAStartup(MAKEWORD(2, 0), &windowsSocketsData); if (rVal != 0) { LOG_IT(LOG::ERROR_MSG, "Initialization of Windows Sockets Data failed - %d ", rVal); return false; } serverSocket = socket(AF_INET, SOCK_STREAM, 0); if (serverSocket == INVALID_SOCKET) { LOG_IT(LOG::ERROR_MSG, "Error at socket() - %d ", WSAGetLastError()); return false; } serverAddress.sin_addr.s_addr = inet_addr(serverIpAddress.c_str()); serverAddress.sin_family = AF_INET; serverAddress.sin_port = htons(sPortNumber); LOG_IT(LOG::SETUP_INFO, "Server Socket is created ... "); return true; } bool ConnectToServer::Connect() { auto rVal = connect(serverSocket, (SOCKADDR*)& serverAddress, sizeof(serverAddress)); if (rVal == SOCKET_ERROR) { LOG_IT(LOG::ERROR_MSG, "connect failed with error code - %d ", WSAGetLastError()); return false; } LOG_IT(LOG::SETUP_INFO, "Connected to the server socket - %d ", serverSocket); return true; } }
SendAndReceiveMessages.h
Once the connection is established. it will send/receive the massages./*************************************************************************************************** // Author: Kunjesh Singh Baghel // Web-page: https://sites.google.com/site/kunjeshsinghbaghel/ ***************************************************************************************************/ #ifndef _SEND_AND_RECEIVE_MESSAGES_ #define _SEND_AND_RECEIVE_MESSAGES_ #ifndef WIN32_LEAN_AND_MEAN // The WIN32_LEAN_AND_MEAN macro prevents the Winsock.h from being included by the Windows.h header #define WIN32_LEAN_AND_MEAN #endif #pragma once #include <winsock2.h> namespace CLIENT_SOCKET { class SendAndReceive { private: SOCKET serverSocket; USHORT sBufferLen; public: /* Default constructor */ SendAndReceive(SOCKET socket); /* Destructor */ ~SendAndReceive(); void Send(const char *msg); bool Receive(); }; } #endif // !_SEND_AND_RECEIVE_MESSAGES_
SendAndReceiveMessages.cpp
/*************************************************************************************************** // Author: Kunjesh Singh Baghel // Web-page: https://sites.google.com/site/kunjeshsinghbaghel/ ***************************************************************************************************/ #include "SendAndReceiveMessages.h" #include "Log.h" #include "GlobalFactory.h" using namespace SESSION; using namespace CONFIGURATION_MANAGER; namespace CLIENT_SOCKET { SendAndReceive::SendAndReceive(SOCKET socket) : serverSocket(socket) { LOG_IT(LOG::SETUP_INFO, "Construction process : SendAndReceive client socket is getting created"); sBufferLen = std::stoi(FactoryInstance::GetGlobalFactory()->GetConfigurationManager()->GetValue("Buffer_size", VALUE)); } SendAndReceive::~SendAndReceive() { LOG_IT(LOG::SETUP_INFO, "Cleanup process : SendAndReceive client socket is getting cleaned up"); } void SendAndReceive::Send(const char* msg) { char Buffer[512]; // creating local buffer. This will help in multi-threaded environment. memset(Buffer, 0, sizeof(Buffer)); std::memcpy(Buffer, msg, 512); size_t byteSend = send(serverSocket, Buffer, sizeof(Buffer), 0); if (byteSend == SOCKET_ERROR) { LOG_IT(LOG::ERROR_MSG, "send failed with error: %d ", WSAGetLastError()); } LOG_IT(LOG::INFO, "Message sent! %s", Buffer); } bool SendAndReceive::Receive() { char Buffer[512]; memset(Buffer, 0, sizeof(Buffer)); auto rVal = recv(serverSocket, Buffer, sizeof(Buffer), 0); if (rVal == SOCKET_ERROR) { LOG_IT(LOG::ERROR_MSG, "send failed with error code - %d " , WSAGetLastError()); return false; } LOG_IT(LOG::INFO, "Received value is - %s", Buffer); return true; } }
Invoke the client and server-side DLLs
Thanks for reading it. To learn more about design patterns and basic design principles, please see my web page.
- You are sending and receiving one massage at a time.
- Code example
-
//____________________________Client side void SendShortMessage() { std::unique_ptr<ConnectToServer> pConnect = std::make_unique<ConnectToServer>(); if (pConnect->IsConnected()) { std::shared_ptr<SendAndReceive> pServer = pConnect->GetSendAndReceive(); pServer->Send("Ping server request-1"); pServer->Receive(); this_thread::sleep_for(chrono::seconds(2)); pServer->Send("Ping server request-2"); pServer->Receive(); this_thread::sleep_for(chrono::seconds(2)); pServer->Send("Ping server request-3"); pServer->Receive(); } else { LOG_IT(LOG::ERROR_MSG, "Connection to server has not been created properly"); } }//____________________________Server side void SmallMsg() { std::unique_ptr<SocketAcceptor> pConnect = std::make_unique<SocketAcceptor>(); if (pConnect->IsServerSocketCreated()) { pConnect->Accept(); std::shared_ptr<Socket> pSocket = pConnect->GetSocket(); int response = 0; string response_msg; while (pSocket->ReceiveShortMsg()) { ++response; response_msg = "Sending data back to client" + std::to_string(response); pSocket->SendToClient(response_msg.c_str()); } } else { LOG_IT(ERROR_MSG, "Opening server connection failed"); } }
- You are sending large files from client to server.
- Code example
-
//____________________________Client side void SendLargeMessage() { std::string filePath = FactoryInstance::GetGlobalFactory()->GetFileName(); filePath = filePath.substr(0, filePath.find_last_of("\\")); filePath += "\\ClientTestFile.txt"; unique_ptr<ifstream> pFile = make_unique<ifstream>(); pFile->open(filePath); if (!pFile->is_open()) { LOG_IT(ERROR_MSG, "Not able to load the file"); } std::unique_ptr<ConnectToServer> pConnect = std::make_unique<ConnectToServer>(); if (pConnect->IsConnected()) { string line; std::shared_ptr<SendAndReceive> pServer = pConnect->GetSendAndReceive(); while (std::getline(*pFile, line)) { pServer->Send(line.c_str()); } } else { LOG_IT(LOG::ERROR_MSG, "Connection to server has not been created properly"); } } //____________________________Server side void LargeMsg() { std::unique_ptr<SocketAcceptor> pConnect = std::make_unique<SocketAcceptor>(); if (pConnect->IsServerSocketCreated()) { pConnect->Accept(); std::shared_ptr<Socket> pSocket = pConnect->GetSocket(); while (pSocket->ReceiveAndLogMessage()) { pSocket->SendToClient("Logged all the data"); } } else { LOG_IT(ERROR_MSG, "Opening server connection failed"); } }
- Multiple clients send messages to the server.
- Code example
-
//____________________________Client side void Client_A() { std::unique_ptr<ConnectToServer> pConnect = std::make_unique<ConnectToServer>(); if (pConnect->IsConnected()) { std::shared_ptr<SendAndReceive> pServer = pConnect->GetSendAndReceive(); pServer->Send("Client_A | Order X "); pServer->Receive(); pServer->Send("Client_A | Order Y "); pServer->Receive(); pServer->Send("Client_A | Order Z "); pServer->Receive(); } else { LOG_IT(INFO, "Connection to server has not been created properly "); } } void Client_B() { std::unique_ptr<ConnectToServer> pConnect = std::make_unique<ConnectToServer>(); if (pConnect->IsConnected()) { std::shared_ptr<SendAndReceive> pServer = pConnect->GetSendAndReceive(); pServer->Send("Client_B | Order 1 "); pServer->Receive(); pServer->Send("Client_B | Order 2 "); pServer->Receive(); pServer->Send("Client_B | Order 3 "); pServer->Receive(); } else { LOG_IT(INFO, "Connection to server has not been created properly "); } } void Client_C() { std::unique_ptr<ConnectToServer> pConnect = std::make_unique<ConnectToServer>(); if (pConnect->IsConnected()) { std::shared_ptr<SendAndReceive> pServer = pConnect->GetSendAndReceive(); pServer->Send("Client_C | Order One "); pServer->Receive(); pServer->Send("Client_C | Order Two "); pServer->Receive(); pServer->Send("Client_C | Order Three "); pServer->Receive(); } else { LOG_IT(INFO, "Connection to server has not been created properly "); } } void MultiClientTest() { thread T1(Client_A); thread T2(Client_B); thread T3(Client_C); T1.join(); T2.join(); T3.join(); } //____________________________Server side void ProcessMultiClientRequest(std::shared_ptr<Socket> pSocket) { Queue <shared_ptr<IMessage > >& Q = Socket::GetClientRequests(); while (true) { std::unique_lock<std::mutex> lockIt(Q.GetMutex()); Q.GetNotified().wait(lockIt, [&]() {return !Q.IsEmpty(); }); shared_ptr<IMessage > msg = Q.Front(); Q.Remove(); string responce = msg->GetMsg(); responce = "Your Order " + responce + "is placed "; pSocket->SendToClient(responce.c_str(), std::stoi(msg->GetClientSocket())); } } void MultiClient() { std::unique_ptr<SocketAcceptor> pConnect = std::make_unique<SocketAcceptor>(); if (pConnect->IsServerSocketCreated()) { std::shared_ptr<Socket> pSocket = pConnect->GetSocket(); std::thread processThread(ProcessMultiClientRequest, pSocket); pConnect->MultiClientAccept(); processThread.join(); } else { LOG_IT(ERROR_MSG, "Opening server connection failed"); } }
Thanks for reading it. To learn more about design patterns and basic design principles, please see my web page.
Comments
Post a Comment