当前位置: 首页 > article >正文

Linux高阶——1124—多进程多任务多线程多任务多路IO转接技术

目录

1、多进程多任务服务器

代码

2、多线程多任务(阻塞IO)

代码

3、关于多路IO转接技术(select、poll、epoll)

关于服务器程序的IO处理

socket

对网络IO处理的过程


1、多进程多任务服务器

代码

#include<sock.c>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
#include<pthread.h>
#include<sys/wait.h>
#define server_ip "192.168.5.133"
#define server_port 9090

void sig_wait(int n)
{
    pid_t zpid;
    while((zpid=waitpid(-1,NULL,WNOHANG))>0)
    {
        printf("thread 0x%x wait success,zpid %d\n",(unsigned int)pthread_self(),zpid);
    }
}

void * thread_wait(void * arg)
{
    struct sigaction act,oact;
    act.sa_handler=sig_wait;
    act.sa_flags=0;
    sigemptyset(&act.sa_mask);
    sigaction(SIGCHLD,&act,&oact);
    sigprocmask(SIG_SETMASK,&act.sa_mask,NULL);
    while(1)
        sleep(1);
}
int main()
{
    sigset_t set,oset;
    sigemptyset(&set);
    sigaddset(&set,SIGCHLD);
    sigprocmask(SIG_SETMASK,&set,&oset);
    pthread_t tid;
    pthread_create(&tid,NULL,thread_wait,NULL);
    pid_t pid;
    struct sockaddr_in client_addr;
    int server_sock;
    int client_sock;
    server_sock=net_initializer(NULL,server_port,128);
    socklen_t addrlen;
    printf("PROCESS MOD  Servers Running...\n");
    char cip[16];
    ssize_t len;
    client_info cf;
    char buf[1500];
    char* msg="Please try again\n";
    char tm[1024];

    while(1)
    {
        addrlen=sizeof(client_addr);
        if((client_sock=ACCEPT(server_sock,(struct sockaddr*)&client_addr,&addrlen))>0)
        {
            pid=fork();
        }
        if(pid>0)
        {

            cf.sockfd=client_sock;
            inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,cf.ip,16);
            cf.port=ntohs(client_addr.sin_port);
            first_response(cf);
        }
        else if(pid==0)
        {
            while((len=RECV(client_sock,buf,sizeof(buf),0))>0)
            {
                if((strcmp(buf,"time\n"))==0)
                {
                    get_time(tm);
                    SEND(client_sock,tm,strlen(tm),MSG_NOSIGNAL);
                    bzero(tm,sizeof(tm));
                }
                else
                {
                    SEND(client_sock,msg,strlen(msg),MSG_NOSIGNAL);
                }
                bzero(buf,sizeof(buf));
            }
            if(len==0)
            {
                printf("client exit\n");
                close(client_sock);
                exit(0);
            }
        }
        else
        {
            perror("fork call failed");
            exit(0);
        }
    }
    close(server_sock);
    printf("server done\n");
    return 0;
}

2、多线程多任务(阻塞IO)

多线程模型,可以在内存调度开销更小的情况下,完成并发任务,提高CPU使用率,加快执行效率

代码层面与多进程也比较相似,当用户递达,为客户端创建处理线程,处理线程随客户端持续

代码

#include<sock.c>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
#include<pthread.h>
#include<sys/wait.h>
#define server_ip "192.168.5.133"
#define server_port 9090


void * thread_customer(void * arg)
{
    int client_sock=*(int*)arg;
    char* msg="Please try again\n";
    int len;

    char buf[1500];
    char tm[1024];

    pthread_detach(pthread_self());

            while((len=RECV(client_sock,buf,sizeof(buf),0))>0)
            {
                if((strcmp(buf,"time\n"))==0)
                {
                    get_time(tm);
                    SEND(client_sock,tm,strlen(tm),MSG_NOSIGNAL);
                    bzero(tm,sizeof(tm));
                }
                else
                {
                    SEND(client_sock,msg,strlen(msg),MSG_NOSIGNAL);
                }
                bzero(buf,sizeof(buf));
            }
            if(len==0)
            {
                printf("client exit\n");
                close(client_sock);
                exit(0);
            }
}
int main()
{
    struct sockaddr_in client_addr;
    int server_sock;
    int client_sock;
    server_sock=net_initializer(NULL,server_port,128);
    socklen_t addrlen;
    printf("PROCESS MOD  Servers Running...\n");
    char cip[16];
    ssize_t len;
    client_info cf;
    pthread_t tid;
    while(1)
    {
        addrlen=sizeof(client_addr);
        if((client_sock=ACCEPT(server_sock,(struct sockaddr*)&client_addr,&addrlen))>0)
        {
            pthread_create(&tid,NULL,thread_customer,(void*)&client_sock);

            cf.sockfd=client_sock;
            inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,cf.ip,16);
            cf.port=ntohs(client_addr.sin_port);
            first_response(cf);
        }
    }
    close(server_sock);
    printf("server done\n");
    return 0;
}

相比于多进程,多线程模型更轻量,无论是内存占用还是调度速度,但是几点需要注意

首先是稳定性问题,多进程模式较为稳定,某个进程异常退出与其他进程无关,但是多线程中,如果某个线程异常可能会导致进程退出

线程要考虑线程同步、线程安全、死锁避免等问题,在一些用户级线程下,线程无法得到时间片,所以在并发模型选择时要仔细斟酌,而后选择多进程亦或多线程

3、关于多路IO转接技术(select、poll、epoll)

多路IO转接技术——sock监听技术

关于服务器程序的IO处理

一个服务器连接了1000个客户端,每个客户端会产生一个socket

单进程非阻塞模式会遍历所有client_sock,并且尝试读写

多进程模式,每个进程分配一个client_sock,此进程读写

但当前的单进程和多进程均为主动处理IO,但这种主动方法不合理,当sock无事件时,不应该主动读取,浪费开销

client_sock——当sock无事件时,不应该主动等待,等就绪时再处理

server_sock——当sock无连接时,等有连接时再处理

socket

每个sock都包含三种标准事件,IN(读事件)、OUT(写事件)、ERR(异常事件)

当缓冲区不为空,有数据待读,对应的client_sock触发读事件

当sock将数据写入sock缓冲区,等待发送时,触发写事件

当操作的sock出现异常,触发异常事件

对网络IO处理的过程

1、sock监听设置,准备监听(IN、OUT、ERR)

2、开始监听(Select or Poll Epoll)

3、sock就绪

4、处理就绪

5、处理数据,读写sock,或三次握手

6、处理完毕——数据读取成功,连接成功

上述只表示IO监听与处理过程,与数据处理协议处理无关

IO监听和数据处理分离


http://www.kler.cn/a/416127.html

相关文章:

  • MySQL中SQL语句的执行过程详解
  • 【Android】Handler 知识总结:应用场景 / 使用方式 / 工作原理 / 源码分析 / 内存泄漏
  • python面向对象编程练习
  • std库锁机制的使用
  • Leetcode热题100-75 颜色分类
  • 浅谈C/C++内存管理
  • Mac airflow 开发环境搭建
  • Rust 基础语法
  • Diffusion中的Unet (DIMP)
  • 芯片测试-RF中的S参数,return loss, VSWR,反射系数,插入损耗,隔离度等
  • Laravel 代理收益排行榜
  • Unity类银河战士恶魔城学习总结(P145 Save Skill Tree 保存技能树)
  • 加载语言包的方式
  • 怎样安装和启动Apache HTTP服务器(httpd)和PHP?
  • uniapp webview web-view组件监听网页变化 url变化 与网页通讯
  • C++设计模式(观察者模式)
  • Vscode阅读C/C++ Code实用教程
  • shell编程(8)
  • 探索温度计的数字化设计:一个可视化温度数据的Web图表案例
  • 【娱乐项目】基于cnchar库与JavaScript的汉字查询工具