Linux网络编程-多进程、多线程服务器

源码

多进程服务器

server.c

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <errno.h>

#define SERV_PORT 8080
#define LISTENQ 10

void sid_child (int signo) {
    pid_t pid;
    int stat;
    while ((pid = waitpid (-1, &stat, WNOHANG)) > 0);
    return;
}

int main (int argc, char **argv) {
    int listenFd, connFd, ret;
    pid_t childPid;
    socklen_t cliLen;
    struct sockaddr_in clientAddr, serverAddr;

    listenFd = socket (AF_INET, SOCK_STREAM, 0);
    if (listenFd < 0) {
        printf ("[server] socket error: %s\n", strerror (errno));
        exit (-1);
    }

    bzero (&serverAddr, sizeof (serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = htonl (INADDR_ANY);
    serverAddr.sin_port = htons (SERV_PORT);
    
    ret = bind (listenFd, (struct sockaddr*) &serverAddr, sizeof (serverAddr));
    if (ret < 0) {
        printf ("[server] bind error: %s\n", strerror (errno));
        exit (-1);
    }

    ret = listen (listenFd, LISTENQ);
    if (ret < 0) {
        printf ("[server] listen error: %s\n", strerror (errno));
        exit (-1);
    }

    signal (SIGCHLD, sid_child);
    while (1) {
        cliLen = sizeof (clientAddr);
        connFd = accept (listenFd, (struct sockaddr*) &clientAddr, &cliLen);
        if ((childPid = fork()) == 0) {
            close (listenFd);
            time_t now;
            time (&now);
            char buf[20] = {0};
            sprintf (buf, "%s", asctime (gmtime (&now)));
            write (connFd, buf, 20);
            close (connFd);
            exit (0);
        }
        close (connFd);
    }
}

多线程服务器

server.c

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include "threadPool.h"

#define SERV_PORT 8080
#define BUF_SIZE 1024
#define LISTENQ 10

int* u_intcpy (int n) {
    int *ret = (int*) malloc (sizeof (int));
    *ret = n;
    return ret;
}

char* join (char *a, char *catb, char *c) {
    char *ret;
    int i = strlen (a), j = strlen (catb), k = strlen (c), n;
    ret = (char*) malloc (sizeof (char) * (i + j + k + 1));
    for (n = 0; n < i; n++)
        ret[n] = a[n];
    for (n = 0; n < j; n++)
        ret[i + n] = catb[n];
    i += j;
    for (n = 0; n < k; n++)
        ret[i + n] = c[n];
    ret[i + n] = 0;
    return ret;   
}

void timeService (int sockFd) {
    time_t now;
    time (&now);
    char buf[20] = {0};
    sprintf (buf, "%s", asctime (gmtime (&now)));
    write (sockFd, buf, 20);
}

void* handle (void *arg) {
    int sockFd = *(int*) arg;
    char c;
    while (1) {
        read (sockFd, &c, 1);
        if (c == '1')
            timeService (sockFd);
        else if (c == '2')
            break;
    }
    free (arg);
    close (sockFd);
}

int main (int argc, char **argv) {
    int listenFd, connFd, ret;
    struct sockaddr_in clientAddr, serverAddr;
    socklen_t cliLen;
    ThreadPool *pool = createThreadPool (10);

    listenFd = socket (AF_INET, SOCK_STREAM, 0);
    if (listenFd < 0) {
        printf("[server] socket error: %s\n", strerror(errno));
        exit(-1);
    }
    bzero (&serverAddr, sizeof (serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = htonl (INADDR_ANY);
    serverAddr.sin_port = htons (SERV_PORT);

    ret = bind (listenFd, (struct sockaddr*) &serverAddr, sizeof (serverAddr));
    if (ret != 0) {
        close(listenFd);
        printf("[server] bind error: %s\n", strerror(errno));
        exit(-1);
    }

    ret = listen (listenFd, LISTENQ);
    if (ret != 0) {
        close(listenFd);
        printf("[server] listen error: %s\n", strerror(errno));
        exit(-1);
    }
    
    while (1) {
        cliLen = sizeof (clientAddr);
        connFd = accept (listenFd, (struct sockaddr*) &clientAddr, &cliLen);
        submitTask (pool, handle, u_intcpy (connFd));
    }
    close (listenFd);
    destoryThreadPool (pool);
}

threadPool.h

#ifndef _ThreadPool
#define _ThreadPool

#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>

typedef struct executor {
    void *(*task) (void *arg);
    void *arg;
    struct executor *next;
} ThreadExecutor;

typedef struct {
    pthread_mutex_t queueLock;
    pthread_cond_t queueReady;
    ThreadExecutor *queueHead; // all tasks waiting to be executed
    int shutdown;
    pthread_t *threadId;
    int maxThreadNum; // number of active thread in pool
    int curQueueSize; // number of task wait in queue
} ThreadPool;

ThreadPool* createThreadPool (int maxThreadNum);

void submitTask (ThreadPool *pool, void *(*task) (void *arg), void *arg);

int destroyThreadPool (ThreadPool *pool);

#endif

threadPool.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h>
#include <string.h>
#include "threadPool.h"

#define TRUE 1
#define FALSE 0

void *threadRoutine (void *arg) {
    ThreadPool *pool = (ThreadPool*) arg;
    while (TRUE) {
        pthread_mutex_lock (&(pool->queueLock)); // lock
        // waiting for task
        while (pool->curQueueSize == 0 && !pool->shutdown)
            pthread_cond_wait (&(pool->queueReady), &(pool->queueLock));
        // exit thread if pool->shutdown is true
        if (pool->shutdown) {
            pthread_mutex_unlock (&(pool->queueLock));
            pthread_exit (NULL);
        }
        assert (pool->curQueueSize != 0);
        assert (pool->queueHead != NULL);
        // get the head in queue
        pool->curQueueSize--;
        ThreadExecutor *executor = pool->queueHead;
        pool->queueHead = executor->next;
        pthread_mutex_unlock (&(pool->queueLock));
        // execute
        (*(executor->task)) (executor->arg);
        free (executor);
        executor = NULL;
    }
    pthread_exit (NULL); // this line should be unreachable
}

ThreadPool* createThreadPool (int maxThreadNum) {
    ThreadPool *pool = (ThreadPool*) malloc (sizeof (ThreadPool));
    bzero (pool, sizeof (ThreadPool));
    pthread_mutex_init (&(pool->queueLock), NULL);
    pthread_cond_init (&(pool->queueReady), NULL);
    pool->maxThreadNum = maxThreadNum;
    pool->threadId = (pthread_t*) malloc (maxThreadNum * sizeof (pthread_t));
    int i;
    for (i = 0; i < maxThreadNum; i++)
        pthread_create (&(pool->threadId[i]), NULL, threadRoutine, pool);
    return pool;
}

void submitTask (ThreadPool *pool, void *(*task) (void *arg), void *arg) {
    ThreadExecutor *newExecutor = (ThreadExecutor*) malloc (sizeof (ThreadExecutor));
    newExecutor->task = task;
    newExecutor->arg = arg;
    newExecutor->next = NULL;

    pthread_mutex_lock (&(pool->queueLock)); // lock
    ThreadExecutor *executor = pool->queueHead;
    if (executor != NULL) {
        while (executor->next != NULL)
            executor = executor->next;
        executor->next = newExecutor;
    }
    else pool->queueHead = newExecutor;
    pool->curQueueSize++;
    pthread_mutex_unlock (&(pool->queueLock)); // unlock
    pthread_cond_signal (&(pool->queueReady)); // notify thread blocked
}

int destroyThreadPool (ThreadPool *pool) {
    if (pool != NULL) {
        if (pool->shutdown)
            return -1;
        pool->shutdown = TRUE;
        pthread_cond_broadcast (&(pool->queueReady)); // notify all sleeping thread
        // blocking to wait for threads
        int i;
        for (i = 0; i < pool->maxThreadNum; i++)
            pthread_join (pool->threadId[i], NULL);
        free(pool->threadId);
        // destroy executor queue
        ThreadExecutor *head = NULL;
        while (pool->queueHead != NULL) {
            head = pool->queueHead;
            pool->queueHead = pool->queueHead->next;
            free(head);
        }
        pthread_mutex_destroy (&(pool->queueLock));
        pthread_cond_destroy (&(pool->queueReady));
        free(pool);
        return 0;
    }
    return -1;
}

客户端

client.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>

#define SERV_IP "127.0.0.1"
#define SERV_PORT 8080
#define BUF_SIZE 512

int main (int argc, char **argv) {
    int sockFd, ret;
    struct sockaddr_in serverAddr;

    sockFd = socket (AF_INET, SOCK_STREAM, 0);

    bzero(&serverAddr, sizeof (serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons (SERV_PORT);
    inet_pton (AF_INET, SERV_IP, &serverAddr.sin_addr);

    ret = connect (sockFd, (struct sockaddr*) &serverAddr, sizeof (serverAddr));
    if (ret < 0) {
      printf ("connect error: %s\n", strerror (errno));
      exit (-1);
    }

    char buf[BUF_SIZE] = {0};
    if (read (sockFd, buf, BUF_SIZE) == 0) {
      printf ("str_cli: server terminated prematurely");
      exit (-1);
    }
    printf ("[server] %s\n", buf);
    
    close (sockFd);
    exit(0);
}

多进程版客户端(模拟多客户端并发)

client.c

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <signal.h>

#define SERV_IP "127.0.0.1"
#define SERV_PORT 8080
#define BUFFER_SIZE 1024

int childRunning = 1;

void sid_child (int signo) {
    pid_t pid;
    int stat;
    while ((pid = waitpid (-1, &stat, WNOHANG)) > 0);
    childRunning = 0;
}

void client () {
    int sockFd, ret;
    struct sockaddr_in serverAddr;
    
    sockFd = socket (AF_INET, SOCK_STREAM, 0);
    if (sockFd < 0) {
        printf("socket error: %s\n", strerror(errno));
        exit(-1);
    }

    bzero (&serverAddr, sizeof (serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons (SERV_PORT);
    inet_pton (AF_INET, SERV_IP, &serverAddr.sin_addr);
    
    ret = connect (sockFd, (struct sockaddr*) &serverAddr, sizeof (serverAddr));
    if (ret != 0) {
        close(sockFd);
        printf("connect error: %s\n", strerror(errno));
        exit(-1);
    }

    char buf[BUFFER_SIZE] = {0};
    write (sockFd, "1", 1);
    if (read (sockFd, buf, BUFFER_SIZE) > 0)
        printf ("[server] %s\n", buf);
    bzero (buf, BUFFER_SIZE);
    write (sockFd, "2", 1);
    close (sockFd);
}

int main (int argc, char **argv) {
    if (argc == 2) {
        int clientNum, clientPid;
        sscanf (argv[1], "%d", &clientNum);
        signal (SIGCHLD, sid_child);
        for (; clientNum > 0; clientNum--) {
            if ((clientPid = fork()) == 0) {
                client ();
                exit (0);
            }
        }
        while (childRunning);
    }

    exit (0);
}

猜你喜欢

转载自blog.csdn.net/qq_37242224/article/details/83756473