Implementing a Network Chat Room in C: Communication and Interface Design

Implementing a Network Chat Room in C: Communication and Interface Design

In this article, we will learn how to implement a simple network chat room using the C programming language. We will divide it into two parts: the server side and the client side. Through these two parts, users can chat in real-time within the same local area network.

1. Environment Setup

Ensure that the following tools are installed in your development environment:

  • GCC Compiler
  • A text editor (such as VSCode, Sublime Text, etc.)

2. Basics of Network Programming

Before we start, we need to understand some basic concepts of network programming:

  • Socket: An endpoint for inter-process communication.
  • IP Address: A unique address that identifies a device.
  • Port Number: A number that identifies a specific service or application.

3. Server-Side Code

First, let’s implement the server-side code. The server is responsible for listening to client requests and handling message forwarding.

3.1 Creating the Server Code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
#define MAX_CLIENTS 10
#define BUFFER_SIZE 1024

int clients[MAX_CLIENTS];

void broadcast_message(const char *message, int sender) {
    for (int i = 0; i < MAX_CLIENTS; i++) {
        if (clients[i] != -1 && clients[i] != sender) {
            send(clients[i], message, strlen(message), 0);
        }
    }
}

int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);

    // Initialize client array
    memset(clients, -1, sizeof(clients));

    // Create socket file descriptor
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("Socket failed");
        exit(EXIT_FAILURE);
    }

    // Set socket options
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));

    // Set socket address structure
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    // Bind socket to the specified IP and PORT
    bind(server_fd, (struct sockaddr *)&address, sizeof(address));

    // Start listening for connection requests, max connections = 3
    listen(server_fd, MAX_CLIENTS);
    printf("Server is listening on port %d\n", PORT);

    while (1) {
        if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) >= 0) {
            printf("New client connected: %d\n", new_socket);
            for(int i=0; i<MAX_CLIENTS; i++) {
                if(clients[i] == -1) {
                    clients[i] = new_socket;
                    break;
                }
            }
            char buffer[BUFFER_SIZE];
            while(1) {
                memset(buffer, '\0', BUFFER_SIZE);
                int bytes_read = read(new_socket , buffer , BUFFER_SIZE);
                if(bytes_read <= 0){
                    printf("Client disconnected: %d\n", new_socket);
                    close(new_socket);
                    break;
                }
                printf("Message from client %d: %s\n", new_socket , buffer);
                broadcast_message(buffer,new_socket);
            }
        }
    }
    return EXIT_SUCCESS;
}

3.2 Compiling and Running the Server

Use the following command to compile and run the server:

gcc server.c -o server
./server

4. Client-Side Code

Next, let’s implement the client-side code. The client is responsible for sending messages to the server and receiving information from other users.

4.1 Creating the Client Code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT     8080
#define BUFFER_SIZE 1024

int main() {
    int sockfd;
    struct sockaddr_in servaddr;
    char buffer[BUFFER_SIZE];

    // Create socket file descriptor
    if ((sockfd = socket(AF_INET, SOCK_STREAM , IPPROTO_TCP)) == -1 ) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    memset(&servaddr,'\0',sizeof(servaddr));

    // Fill service information structure
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(PORT);

    if(inet_pton(AF_INET,"127.0.0.1",&servaddr.sin_addr)<=0) {
        perror("Invalid address or Address not supported");
        exit(EXIT_FAILURE);
    }

    if(connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr))<0) {
        perror("Connection Failed");
        exit(EXIT_FAILURE);
    }

    while(1) {
        printf("Enter message: ");
        fgets(buffer , BUFFER_SIZE , stdin);
        send(sockfd , buffer , strlen(buffer), MSG_NOSIGNAL );
        memset(buffer,'\0',BUFFER_SIZE);
        recv(sockfd , buffer , BUFFER_SIZE , MSG_WAITALL );
        printf("%s\n" , buffer );
    }
    close(sockfd);
    return EXIT_SUCCESS;
}

4.2 Compiling and Running the Client

Use the following command to compile and run multiple client instances:

gcc client.c -o client
./client # Execute this command multiple times in different terminals to start multiple client instances.

Conclusion

By following the above steps, you have successfully created a simple network chat room based on the C language. In this chat room, users can send messages to each other without the need for any additional software support. This is a great exercise to help you understand the basic concepts of network programming and how to utilize C for practical application development.

We hope you continue to explore more complex features, such as adding usernames, private messaging, etc.

Leave a Comment