Socket Programming in C for Beginners | Group Chat Application | Multi Threaded + Multiple Users|E4|

4 min read 1 year ago
Published on Aug 05, 2024 This response is partially generated with the help of AI. It may contain inaccuracies.

Table of Contents

Introduction

In this tutorial, we'll learn how to create a group chat application using socket programming in C. This application will allow multiple clients to connect to a server and communicate with each other in real time. By the end of this tutorial, you'll have a solid understanding of socket programming concepts, threading, and how to implement a simple chat server.

Step 1: Setting Up the Environment

  1. Choose an IDE: You can use any IDE of your choice, such as CLion or Code::Blocks.
  2. Create a new project: Name it “socket_server” for the server-side application and “socket_client” for the client-side application.
  3. Include necessary headers: Make sure to include the following headers in your C files:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <pthread.h>
    

Step 2: Creating the Server

  1. Create the socket:

    • Use the socket() function to create a server socket.
    • Specify the address family (IPv4), socket type (TCP), and protocol (0).
    int server_socket = socket(AF_INET, SOCK_STREAM, 0);
    
  2. Bind the socket:

    • Define the server address structure and bind the socket to an IP and port.
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY; // Listen on all interfaces
    server_addr.sin_port = htons(2000);  // Port number
    bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));
    
  3. Listen for incoming connections:

    • Use the listen() function to allow the server to accept incoming connections.
    listen(server_socket, 10); // 10 is the backlog for incoming connections
    
  4. Accept clients:

    • Use a loop to accept multiple clients. Create a new thread for each accepted client.
    while (1) {
        int client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &addr_size);
        pthread_t tid;
        pthread_create(&tid, NULL, handle_client, (void*)&client_socket);
    }
    

Step 3: Handling Client Connections

  1. Create a function to handle client communication:

    • This function will receive messages from the client and broadcast them to other connected clients.
    void* handle_client(void* arg) {
        int client_socket = *(int*)arg;
        char buffer[1024];
        while (1) {
            int bytes_received = recv(client_socket, buffer, sizeof(buffer), 0);
            if (bytes_received <= 0) {
                break; // Connection closed
            }
            // Broadcast the message to other clients
            broadcast_message(buffer, client_socket);
        }
        close(client_socket);
        return NULL;
    }
    
  2. Broadcast messages:

    • Implement a function that sends messages to all connected clients except the sender.
    void broadcast_message(char* message, int sender_socket) {
        for (int i = 0; i < accepted_clients_count; i++) {
            if (accepted_clients[i] != sender_socket) {
                send(accepted_clients[i], message, strlen(message), 0);
            }
        }
    }
    

Step 4: Creating the Client

  1. Create the client socket:

    • Similar to the server, use the socket() function.
    int client_socket = socket(AF_INET, SOCK_STREAM, 0);
    
  2. Connect to the server:

    • Define the server address and connect using the connect() function.
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(2000); // Port number
    inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr); // Server IP
    connect(client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));
    
  3. Send and receive messages:

    • Use a loop to send messages from the client and listen for incoming messages from the server.
    while (1) {
        char message[1024];
        fgets(message, sizeof(message), stdin);
        send(client_socket, message, strlen(message), 0);
        // Listen for incoming messages in a separate thread
    }
    

Step 5: Implementing Multi-threaded Client Listening

  1. Create a separate thread for receiving messages:

    • This thread will continuously listen for incoming messages from the server.
    void* listen_for_messages(void* arg) {
        int client_socket = *(int*)arg;
        char buffer[1024];
        while (1) {
            int bytes_received = recv(client_socket, buffer, sizeof(buffer), 0);
            if (bytes_received <= 0) {
                break; // Connection closed
            }
            printf("Received: %s\n", buffer);
        }
        return NULL;
    }
    
  2. Start the thread:

    • Call this thread when the client connects to the server.
    pthread_t tid;
    pthread_create(&tid, NULL, listen_for_messages, (void*)&client_socket);
    

Conclusion

You have successfully created a multi-threaded group chat application using socket programming in C. This application allows multiple clients to connect to a server and communicate with each other in real time. As next steps, consider adding features like user authentication, chat history, or deploying the application to a server for broader access. Experiment with error checking and memory management to enhance the robustness of your application.