Network Programming in C: Basics of Socket Programming

In modern computer networks, a socket is the fundamental interface for network communication. Through sockets, programs can transfer data between different hosts. This article will introduce how to implement simple network programming using C, including creating a server and a client.

1. Introduction to Sockets

A socket is a mechanism for inter-process communication that provides a set of APIs to support data transmission under the TCP/IP protocol suite. In C, we typically use the headers <span><sys/socket.h></span>, <span><netinet/in.h></span>, and <span><arpa/inet.h></span> for network programming.

1.1 Socket Types

  • Stream Socket (SOCK_STREAM): Used for TCP protocol, providing a reliable two-way connection.
  • Datagram Socket (SOCK_DGRAM): Used for UDP protocol, does not guarantee the order and integrity of packets.

2. Creating a Simple TCP Server

Next, we will create a simple TCP server that can accept client connections and echo back the received data.

2.1 Code Example

#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 server_fd, new_socket;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);
    char buffer[BUFFER_SIZE] = {0};

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

    // Set socket options for address reuse
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }

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

    // Bind socket to specified port
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    // Start listening for connection requests
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    printf("Server is listening on port %d\n", PORT);

    while(1) {
        // Accept new connection requests
        if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) {
            perror("accept");
            exit(EXIT_FAILURE);
        }
        read(new_socket , buffer, BUFFER_SIZE);
        printf("Received: %s\n", buffer);
        send(new_socket , buffer , strlen(buffer), 0);
        printf("Echoed back: %s\n", buffer);
        close(new_socket);
    }
    return 0;
}

2.2 Program Explanation

  • socket(): Creates a new socket.
  • setsockopt(): Sets options to allow address reuse.
  • bind(): Binds the created socket to a specific address and port.
  • listen(): Starts listening for connection requests from clients.
  • accept(): Accepts a pending connection and returns a new socket descriptor for communication with that client.
  • read()/send(): Reads data from the client and sends it back.

3. Creating a Simple TCP Client

Now we will implement a simple TCP client that can send messages to the server and print the data returned from the server.

3.1 Client Code Example

#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 sock = 0;
    struct sockaddr_in serv_addr;
    char *hello = "Hello from client";
    char buffer[BUFFER_SIZE] = {0};

    if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
        perror("Socket creation error");
        return -1;
    }
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);

    if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0) {
        printf("\nInvalid address/ Address not supported \n");
        return -1;
    }

    if (connect(sock, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) != -1 ) {
        send(sock , hello , strlen(hello), MSG_NOSIGNAL );
        read(sock , buffer , BUFFER_SIZE);
        printf("%s\n",buffer);
    } else {
        perror("Connection Failed");
        return -1;
    }
    close(sock);
    return 0;
}

### 3.2 Program Explanation

– Similar to the server, a new socket needs to be created first, then configure the target address information, including IP and port number. – Use the <span>connect()</span> function to establish a connection with the server. If successful, messages can be sent using the <span>send()</span> function and response data can be read using the <span>read()</span> function.

## 4. Compiling and Running the Program

Make sure you have the GCC compiler installed. You can compile and run the server and client with the following commands:

# Compile server code: gcc server.c -o server
# Compile client code: gcc client.c -o client
# First run the server: ./server
# In another terminal window run the client: ./client

## 5. Conclusion

This article introduced how to implement basic network programming using C, by building simple TCP server and client applications, allowing readers to understand the basic concepts of sockets and their operational processes. We hope this article helps you get started with C network programming!

Leave a Comment