3.多进程、多线程并发服务器

多进程服务端代码:

#include <serversocket.h>
#include <clientsocket.h>
#include <iostream>
#include <signal.h>
#include <sys/wait.h>

using namespace std;
ServerSocket ssocket;
ClientSocket clientSocket;

//父进程退出时的信号处理函数
void sighandle_term(int sig)
{
    //防止信号处理函数被新的信号中断
    signal(SIGINT, SIG_IGN);
    signal(SIGTERM, SIG_IGN);

    //通知进程组内所有子进程退出
    kill(0, SIGTERM);
    ssocket.close();
    exit(0);
}

//子进程退出时父进程的信号处理函数
void sighandle_chld(int sig)
{
    //防止信号处理函数被新的信号中断
    signal(SIGINT, SIG_IGN);
    signal(SIGTERM, SIG_IGN);

    int pid;
    while(pid = waitpid(-1, NULL, WNOHANG) > 0)
    {
        cout << "child process exited, pid = " << pid << endl;
    }    

    signal(SIGINT, sighandle_term);
    signal(SIGTERM, sighandle_term);
}

//子进程退出时子进程的信号处理函数
void sighandle_childExit(int sig)
{
    //防止信号处理函数被新的信号中断
    signal(SIGINT, SIG_IGN);
    signal(SIGTERM, SIG_IGN);

    clientSocket.close();
    exit(0);
}

int main()
{
    signal(SIGCHLD, sighandle_chld);
    signal(SIGINT, sighandle_term);
    signal(SIGTERM, sighandle_term);

    clientSocket.close();
    if (ssocket.fd() < 0)
    {
        exit(1);
    }

    char host[] = "127.0.0.1";
    int port = 9998;
    if (!ssocket.bind(host, port))
    {
        ssocket.close();
        exit(1);
    }
    if (!ssocket.listen(128))
    {
        ssocket.close();
        exit(1);
    }

    while (true)
    {
        int cfd = ssocket.accept();
        if (cfd < 0)
        {
            ssocket.close();
            exit(1);
        }
        ClientSocket csocket(cfd);

        int pid = fork();
        if (pid > 0)
        {
            csocket.close();
            continue;
        }
        else if(pid < 0)  //系统资源不足
        {
            perror("fork error:");
            ssocket.close();
            csocket.close();
            exit(1);
        }

        signal(SIGINT, sighandle_childExit);
        signal(SIGTERM, sighandle_childExit);

        clientSocket.setFd(cfd);
        ssocket.close();
        char recvbuf[1024];
        if (csocket.recv(recvbuf, sizeof(recvbuf)) < 0)
        {
            csocket.close();
            exit(1);
        }
        cout << "Recieve: clientfd = " << cfd << ", message = " << recvbuf << endl;

        char sendbuf[] = "Server recieved your message";
        if (csocket.send(sendbuf, sizeof(sendbuf)) < 0)
        {
            csocket.close();
            exit(1);
        }

        csocket.close();
        exit(0);
    }

    ssocket.close();
    return 0;
}

多线程服务端代码:

#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <pthread.h>
#include <serversocket.h>
#include <clientsocket.h>
using namespace std;

void *task_thread(void *arg)
{
    ClientSocket client = *(ClientSocket *)arg;
    char recvbuf[1024] = {0};
    size_t len = client.recv(recvbuf, sizeof(recvbuf));
    if (len > 0)
    {
        cout << "recieved from client: " << recvbuf << endl;
        char sendbuf[1024] = "recieved your message";
        client.send(sendbuf, sizeof(sendbuf));
    }
    client.close();
}

int main()
{
    char host[] = "127.0.0.1";
    int port = 9999;
    ServerSocket ssocket;
    if (ssocket.fd() < 0)
    {
        exit(1);
    }
    if (!ssocket.bind(host, port))
    {
        ssocket.close();
        exit(1);
    }
    if (!ssocket.listen(128))
    {
        ssocket.close();
        exit(1);
    }

    while (true)
    {
        int connfd = ssocket.accept();
        if (connfd < 0)
        {
            continue;
        }
        ClientSocket csocket(connfd);

        pthread_t tid = -1;
        //设置线程分离属性
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
        int ret = pthread_create(&tid, &attr, task_thread, &csocket);
        if (ret != 0)
        {
            perror("create thread failed:");
            exit(1);
        }
    }

    ssocket.close();
    return 0;
}

线程独立资源包括:栈空间、线程id、errno变量、信号屏蔽字、调度优先级,共享的资源有:堆空间、文件描述符表、信号处理方法、当前工作目录、用户id和组id

pthread_t pthread_self(); 该函数总是成功

int pthread_equal(pthread_t t1, pthread_t t2); 相同返回非0

int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void ),void arg);

attr参数一般为NULL

#include<pthread.h>

CmakeLists: link_libraries(pthread)

pthread有两种状态:joinable非分离和unjoinable分离

joinable状态,当线程函数自己返回退出时或pthread_exit()时都不会释放线程占用的堆栈和线程描述符(总计8k多),只有调用了pthread_join之后资源才会被释放。

unjoinable状态,资源在线程函数退出或pthread_exit时自动释放。该状态可以在创建线程时指定,或在线程创建之后在线程函数开头detach自己:pthread_detach(pthread_self()),在线程函数中就可以直接调用pthread_exit(NULL)退出。

int pthread_join(pthread_t thread, void retval):**子线程合入主线程,主线程阻塞并等待子线程结束。

retval是用户定义的指针,用来存储被等待线程的返回值。

返回0代表成功,失败返回的是错误号。

int pthread_detach(pthread_t tid),成功后返回0,如果tid是分离线程或者不是当前进程中的有效线程则返回错误。

分离状态的线程不可以被join

void pthread_exit(void retval)* 内部结束,线程终止,返回数据

int pthread_cancel(pthread_t thread) 线程函数外部取消线程

线程清理:

void pthread_cleanup_push(void (routine)(void), void* arg);

void pthread_cleanup_pop(int execute);

线程属性:

pthread_attr_t
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

  • 15
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值