Skip to content

Instantly share code, notes, and snippets.

@chinhvo
Forked from redatawfik/server.cpp
Created November 16, 2024 06:19
Show Gist options
  • Save chinhvo/e89971546098b76bbe9da27fc76d4dfe to your computer and use it in GitHub Desktop.
Save chinhvo/e89971546098b76bbe9da27fc76d4dfe to your computer and use it in GitHub Desktop.
Server implementation of client-server chat using Winsock
#include <winsock2.h>
#include <iostream>
struct CLIENT_INFO {
SOCKET hClientSocket;
struct sockaddr_in clientAddr;
};
char szServerIPAddr[] = "192.168.1.4"; // Put here the IP address of the server
int nServerPort = 5050; // The server port that will be used by
// clients to talk with the server
bool InitWinSock2_0();
BOOL WINAPI ClientThread(LPVOID lpData);
using namespace std;
int main() {
if (!InitWinSock2_0()) {
cout << "Unable to Initialize Windows Socket environment" << WSAGetLastError() << endl;
return -1;
}
SOCKET hServerSocket;
hServerSocket = socket(
AF_INET, // The address family. AF_INET specifies TCP/IP
SOCK_STREAM, // Protocol type. SOCK_STREM specified TCP
0 // Protoco Name. Should be 0 for AF_INET address family
);
if (hServerSocket == INVALID_SOCKET) {
cout << "Unable to create Server socket" << endl;
// Cleanup the environment initialized by WSAStartup()
WSACleanup();
return -1;
}
// Create the structure describing various Server parameters
struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET; // The address family. MUST be AF_INET
serverAddr.sin_addr.s_addr = inet_addr(szServerIPAddr);
serverAddr.sin_port = htons(nServerPort);
// Bind the Server socket to the address & port
if (bind(hServerSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
cout << "Unable to bind to " << szServerIPAddr << " port " << nServerPort << endl;
// Free the socket and cleanup the environment initialized by WSAStartup()
closesocket(hServerSocket);
WSACleanup();
return -1;
}
// Put the Server socket in listen state so that it can wait for client connections
if (listen(hServerSocket, SOMAXCONN) == SOCKET_ERROR) {
cout << "Unable to put server in listen state" << endl;
// Free the socket and cleanup the environment initialized by WSAStartup()
closesocket(hServerSocket);
WSACleanup();
return -1;
}
// Start the infinite loop
while (true) {
// As the socket is in listen mode there is a connection request pending.
// Calling accept( ) will succeed and return the socket for the request.
SOCKET hClientSocket;
struct sockaddr_in clientAddr;
int nSize = sizeof(clientAddr);
hClientSocket = accept(hServerSocket, (struct sockaddr *) &clientAddr, &nSize);
if (hClientSocket == INVALID_SOCKET) {
cout << "accept( ) failed" << endl;
} else {
HANDLE hClientThread;
struct CLIENT_INFO clientInfo;
DWORD dwThreadId;
clientInfo.clientAddr = clientAddr;
clientInfo.hClientSocket = hClientSocket;
cout << "Client connected from " << inet_ntoa(clientAddr.sin_addr) << endl;
// Start the client thread
hClientThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) ClientThread,
(LPVOID) &clientInfo, 0, &dwThreadId);
if (hClientThread == NULL) {
cout << "Unable to create client thread" << endl;
} else {
CloseHandle(hClientThread);
}
}
}
closesocket(hServerSocket);
WSACleanup();
return 0;
}
bool InitWinSock2_0() {
WSADATA wsaData;
WORD wVersion = MAKEWORD(2, 0);
return !WSAStartup(wVersion, &wsaData);
}
BOOL WINAPI ClientThread(LPVOID lpData) {
CLIENT_INFO *pClientInfo = (CLIENT_INFO *) lpData;
char szBuffer[1024];
int nLength;
while (1) {
nLength = recv(pClientInfo->hClientSocket, szBuffer, sizeof(szBuffer), 0);
if (nLength > 0) {
szBuffer[nLength] = '\0';
cout << "Received " << szBuffer << " from " << inet_ntoa(pClientInfo->clientAddr.sin_addr) << endl;
// Convert the string to upper case and send it back, if its not QUIT
strupr(szBuffer);
if (strcmp(szBuffer, "QUIT") == 0) {
closesocket(pClientInfo->hClientSocket);
return TRUE;
}
// send( ) may not be able to send the complete data in one go.
// So try sending the data in multiple requests
int nCntSend = 0;
char *pBuffer = szBuffer;
while ((nCntSend = send(pClientInfo->hClientSocket, pBuffer, nLength, 0) != nLength)) {
if (nCntSend == -1) {
cout << "Error sending the data to " << inet_ntoa(pClientInfo->clientAddr.sin_addr) << endl;
break;
}
if (nCntSend == nLength)
break;
pBuffer += nCntSend;
nLength -= nCntSend;
}
} else {
cout << "Error reading the data from " << inet_ntoa(pClientInfo->clientAddr.sin_addr) << endl;
}
}
return TRUE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment