Unix system programming (4) – multi-process concurrent server

1. Iterative Server & Concurrent Server

Servers can be divided into:

1.1 Iteration server

An iterative server can only handle one client’s request at a time. That is to say, when the server responds to a client request, if another client initiates a request, it cannot get a timely response. The following figure is a typical iterative server processing flow.

1.2 Concurrent Server

[A concurrent] server can handle multiple client requests at the same time. The following figure is a concurrent server processing flow based on the multi-process model.

2. Multi-process concurrent server

1. The client calls connet to initiate a connection

2. The server accepts blocking and returns, and the connection is established successfully

3. The server calls fork() to create a child process

4. The server closes the connection socket, and the child process closes the listening socket

5. The child process processes client requests, and the parent process continues to be in the accept() blocking listening state.

3. Simple implementation

The source code can be downloaded from: [Github link] .

Server-side source code:

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>

#define SERV_PORT 8000
#define MAXLINE 1024

int main()
{
    int fd, confd, clientaddrlen, revlen, i;
    struct sockaddr_in serveraddr, clientaddr;
    char str[INET_ADDRSTRLEN];
    char buf[MAXLINE];
    pid_t pid;

    //1. Create a socket 
    fd = socket(AF_INET, SOCK_STREAM, 0 );

    //2. Bind a port 
    bzero(&serveraddr, sizeof (serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(SERV_PORT);
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

    bind(fd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));

    //3. Set listening 
    listen(fd, 20 );
     printf ( "Accepting Connecting...\n" );

    while(1)
    {
        //4. Accept the link 
        clientaddrlen = sizeof (clientaddr);
        confd = accept(fd, (struct sockaddr*)&clientaddr, &clientaddrlen);

        pid = fork();
        if(pid == 0)
        {
            close(fd);
            while(1)
            {
                revlen = read(confd, buf, MAXLINE);
                if(revlen == 0)
                {
                    printf("closed\n");
                    break;
                }
                printf("client: %s\t port: %d\n",
                inet_ntop(AF_INET, &clientaddr.sin_addr, str, sizeof(str)),
                ntohs(clientaddr.sin_port));
                i = 0;
                while(i < revlen)
                {
                    buf[i] = toupper(buf[i]);
                    ++i;
                }
                write(confd, buf, revlen);
            }
            close(confd);
            return 0;
        }
        else if(pid > 0)
        {
            close(confd);
        }
        else
        {
            printf("fork err\n");
        }
    }
    close(fd);
    return 0;
}

Test client source code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define MAXLINE 80
#define SERV_PORT 8000

int main(int argc, char *argv[])
{
    //sockaddr_in IPv4
    struct sockaddr_in servaddr;
    char buf[MAXLINE];
    int sockfd, n;

    //1. Create a socket 
    sockfd = socket(AF_INET, SOCK_STREAM, 0 );

    //2. Link to the local 8000 port server 
    bzero(&servaddr, sizeof (servaddr));
    servaddr.sin_family = AF_INET;
    inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
    servaddr.sin_port = htons(SERV_PORT);
    connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    while(fgets(buf, MAXLINE, stdin) != NULL)
    {
        //3. Send data to the server 
        write(sockfd, buf, strlen (buf));
         //4. Read the returned data from the server
        n = read(sockfd, buf, MAXLINE);
        printf("Response from server:\n");
        write(STDOUT_FILENO, buf, n);
    }
    //5. Close the socket descriptor
    close(sockfd);
    return 0;
}

Leave a Comment

Your email address will not be published. Required fields are marked *