1.
Include Header Files
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <windows.h>
• #include <stdio.h>: Includes standard input/output functions.
• #include <stdlib.h>: Includes standard library functions like exit.
• #include <winsock2.h>: Includes the Winsock library for network programming on
Windows.
• #include <windows.h>: Includes Windows API functions.
2. Link to Winsock Library
#pragma comment(lib, "ws2_32.lib") // Winsock Library
• This line tells the compiler to link against the ws2_32.lib, which is the library needed for
using Winsock functions.
3. Function Declarations
void handle_client(SOCKET client_socket);
• Declares a function handle_client that takes a SOCKET type parameter, which will be
used to communicate with a connected client.
4. Client Thread Function
DWORD WINAPI ClientThread(LPVOID lpParam) {
SOCKET client_socket = (SOCKET)(intptr_t)lpParam; // Cast the parameter back to SOCKET
handle_client(client_socket);
return 0;
• DWORD WINAPI ClientThread(LPVOID lpParam): This defines a thread function that will
handle client connections.
o Parameters:
▪ LPVOID lpParam: A generic pointer that can hold any type of data. Here,
it is expected to be a SOCKET.
o The function casts lpParam back to a SOCKET and calls handle_client to process
the client.
o Returns 0 to indicate successful completion.
5. Main Function
int main() {
• The entry point of the program.
6. Winsock Initialization
WSADATA wsa;
• A structure that holds information about the Winsock implementation.
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
• Initializes the Winsock DLL.
o MAKEWORD(2, 2): Specifies the version of Winsock to be used (2.2).
o &wsa: A pointer to a WSADATA structure that receives information about the
Winsock implementation.
• If initialization fails, it prints an error and exits.
7. Create a Socket
SOCKET server_socket, client_socket;
• Declares two socket variables: server_socket for listening for incoming connections and
client_socket for communication with a client.
if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
• Creates a socket:
o AF_INET: Specifies IPv4 protocol.
o SOCK_STREAM: Specifies TCP (connection-oriented) protocol.
o 0: The default protocol for TCP.
• Checks if the socket was created successfully.
8. Configure Server Address
struct sockaddr_in server_address, client_address;
• Defines structures for server and client addresses.
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = INADDR_ANY;
server_address.sin_port = htons(3001);
• Configures the server address:
o sin_family: Address family (IPv4).
o sin_addr.s_addr: Set to INADDR_ANY to accept connections on any available
interface.
o sin_port: Port number (3001), converted to network byte order using htons().
9. Bind the Socket
if (bind(server_socket, (struct sockaddr *)&server_address, sizeof(server_address)) ==
SOCKET_ERROR) {
• Binds the socket to the specified address and port.
o (struct sockaddr *)&server_address: Casts the server address to the correct
type.
o sizeof(server_address): Size of the server address structure.
10. Listen for Incoming Connections
listen(server_socket, 3);
• Puts the server socket in a listening state, allowing it to accept incoming connections.
The second parameter (3) is the maximum length of the queue of pending connections.
11. Accept Connections in a Loop
while (1) {
client_socket = accept(server_socket, (struct sockaddr *)&client_address,
&client_address_len);
• Enters an infinite loop to accept incoming client connections.
• accept() blocks until a client connects, returning a new socket (client_socket) for
communication with that client.
12. Create a New Thread for Each Client
hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)(intptr_t)client_socket, 0, NULL);
• Creates a new thread for each client:
o NULL: Default security attributes.
o 0: Default stack size.
o ClientThread: Function to run in the new thread.
o (LPVOID)(intptr_t)client_socket: Casts the client_socket to LPVOID for passing
as a parameter.
o 0: Default creation flags.
o NULL: No thread identifier is needed.
• If thread creation fails, it closes the client socket.
CloseHandle(hThread); // Close the thread handle in the parent thread
• Closes the thread handle in the parent (main) thread.
13. Close the Server Socket
closesocket(server_socket);
WSACleanup();
return 0;
• Closes the listening server socket and cleans up Winsock resources.
14. Handle Client Function
void handle_client(SOCKET client_socket) {
• Defines the function to handle communication with a connected client.
int num1, num2, result;
recv(client_socket, (char *)&num1, sizeof(num1), 0);
recv(client_socket, (char *)&num2, sizeof(num2), 0);
• Receives two integers from the client through the client_socket.
result = num1 + num2;
send(client_socket, (char *)&result, sizeof(result), 0);
• Calculates the sum of the two integers and sends the result back to the client.
closesocket(client_socket);
• Closes the client socket after the communication is done.
Summary
This server program uses a multithreaded approach to handle multiple client connections. It
initializes Winsock, creates a listening socket, accepts incoming connections in a loop, and
creates a new thread for each client to handle their requests independently. The
communication is done by sending and receiving integers, specifically summing two integers
sent by the client.