Client-Server Communication in C: Examples and Code

Client Program Example (AF_INET, Stream)

This is an example of a client program using the AF_INET family type and stream sockets that sends messages to a server program. The functions leer_linea and escribir_linea are assumed to be defined in the file comun.c.


void escribir_mensaje(int s);

int main() {
    int sd;
    struct sockaddr_in dirser;

    if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("Error creating socket");
        return 1;
    }

    dirser.sin_family = AF_INET;
    dirser.sin_port = htons(7000);
    dirser.sin_addr.s_addr = inet_addr("127.0.0.1");

    if (connect(sd, (struct sockaddr *)&dirser, sizeof(dirser)) == -1) {
        perror("Error connecting to server");
    } else {
        escribir_mensaje(sd);
    }

    close(sd);
    return 0;
}

void escribir_mensaje(int s) {
    char msg[80], mensa[80];
    int nbytes;

    puts("Give me a message");

    if ((nbytes = read(0, msg, sizeof(msg))) == -1) {
        perror("Error reading message from keyboard");
    } else {
        msg[nbytes - 1] = '\0';
        write(s, msg, strlen(msg) + 1);
        printf("Message Sent: %s\n", msg);
        read(s, mensa, sizeof(mensa));
        printf("Received message: %s\n", mensa);
    }
}

Concurrent Server Program Example (AF_INET, Stream)

This is a sample concurrent server program using the AF_INET family and stream sockets. It receives messages from client programs, displays them, and sends them back to the client along with its process ID (PID). The functions leer_linea and escribir_linea are assumed to be defined in the file comun.c. To end the program, you would typically use a signal or a specific input sequence.


void recibir_mensaje(int s);

int main() {
    struct sockaddr_in dirser, dircli; // Server and client addresses
    int sd, nsd, longcli, ret, cont = 0;

    longcli = sizeof(dircli);

    if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("Error creating socket");
        return 1;
    }

    dirser.sin_family = AF_INET;
    dirser.sin_port = htons(7000);
    dirser.sin_addr.s_addr = inet_addr("127.0.0.1");

    if (bind(sd, (struct sockaddr *)&dirser, sizeof(dirser)) == -1) {
        perror("Failed to publish the address of the server");
        return 1;
    }

    if (listen(sd, 5) == -1) {
        perror("Error creating customer queue");
        return 1;
    }

    while (1) {
        printf("Connection Pending, PID: %d\n", getpid());

        if ((nsd = accept(sd, (struct sockaddr *)&dircli, &longcli)) == -1) {
            perror("Error receiving request");
        } else {
            printf("Connection accepted\n");

            if ((ret = fork()) == -1) {
                perror("Error duplicating process");
            } else {
                if (ret == 0) { // Child process
                    close(sd); 
                    recibir_mensaje(nsd);
                    printf("Client %d served\n", cont + 1);
                    close(nsd);
                    exit(0);
                } else { // Parent process
                    close(nsd);
                    cont++;
                }
            }
        }
    }
    return 0;
}

void recibir_mensaje(int s) {
    char msg[80], mensa[80];
    int nbytes;

    if ((nbytes = read(s, msg, sizeof(msg))) == -1) {
        perror("Error reading message from client");
    } else {
        msg[nbytes - 1] = '\0';
        printf("Message received: %s\n", msg);
        sprintf(mensa, "%s %d", msg, getpid());
        write(s, mensa, strlen(mensa) + 1);
    }
}

Connectionless Server Example (AF_INET, Datagram)

This is an interactive server using the AF_INET family and datagram sockets. It receives messages from a client, displays them, and resends them with the PID of the server that handled the request.


int main() {
    int sd;
    struct sockaddr_in dirser, dircli;
    char msg[80], mensa[80];
    int nb, longd = sizeof(dircli); // Address length

    if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        perror("Error creating socket");
        return 1;
    }

    dirser.sin_family = AF_INET;
    dirser.sin_port = htons(7000);
    dirser.sin_addr.s_addr = inet_addr("127.0.0.1");

    if (bind(sd, (struct sockaddr *)&dirser, sizeof(dirser)) == -1) {
        perror("Failed to publish the address of the server");
        return 1;
    }

    if ((nb = recvfrom(sd, msg, sizeof(msg), 0, (struct sockaddr *)&dircli, &longd)) == -1) {
        perror("Error receiving data");
    } else {
        msg[nb - 1] = '\0';
        printf("Message received: %s\n", msg);
        sprintf(mensa, "PID server: %d, %s", getpid(), msg);
        sendto(sd, mensa, strlen(mensa) + 1, 0, (struct sockaddr *)&dircli, sizeof(dircli));
    }
    return 0;
}

UDP Client Example


int main() {
    int sd;
    struct sockaddr_in dirser, dircli;
    char msg[80], mensa[80];
    int nb, longd = sizeof(dircli);

    if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        perror("Error creating socket");
        return 1;
    }

    dircli.sin_family = AF_INET;
    dircli.sin_port = htons(0); // Let the system assign a port
    dircli.sin_addr.s_addr = INADDR_ANY; // Any available interface

    if (bind(sd, (struct sockaddr *)&dircli, sizeof(dircli)) == -1) {
        perror("Failed to acquire the address of the client");
        return 1;
    }

    dirser.sin_family = AF_INET;
    dirser.sin_port = htons(7000);
    dirser.sin_addr.s_addr = inet_addr("127.0.0.1");

    puts("Enter message");

    if ((nb = read(0, msg, sizeof(msg))) == -1) {
        perror("Error reading from input");
    } else {
        msg[nb - 1] = '\0';
        sendto(sd, msg, strlen(msg) + 1, 0, (struct sockaddr *)&dirser, sizeof(dirser));
        printf("Message Sent: %s\n", msg);

        if ((nb = recvfrom(sd, mensa, sizeof(mensa), 0, (struct sockaddr *)&dirser, &longd)) == -1) {
            perror("Error receiving data");
        } else {
            mensa[nb - 1] = '\0';
            printf("Message received from server: %s\n", mensa);
        }
    }
    return 0;
}