TCP并发服务器

一、整体框架

二、 服务器
单循环服务器:同一时刻,只能处理一个客户端的任务

并发服务器:同一时刻,只能处理多个客户端的任务

UDP 是具备并发性的,是因为UDP是无连接的,所以处理器可以处理过来

TCP实际上是单循环的服务器,只能建立一对一连接,其他人不能再与其建立连接,之前只有一个套接字

现状为了实现并发,我们给每一个连接都给予一个套接字

三、TCP并发务器
3.1、多进程​    

执行流程:

  1. ​socket()
  2. ​bind()
  3. listen()
  4. accept() 
  5. fork()
3.2、多线程
#include<head.h>
 
void *doSth(void *arg)
{
    int connfd = *((int *)arg); 
    while(1)
    {
        char buff[1024] = {0};
        ssize_t size = recv(connfd,buff,sizeof(buff),0);
        if(size <= 0)
        {
            break;
        }
        printf("cli--------->%s\n",buff);
        strcat(buff,"----->ok!");
        send(connfd,buff,strlen(buff),0);
    }
    close(connfd);
}
int conct(const char *ip,unsigned short port)
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd == -1)
    {
        return -1;
    }
    struct sockaddr_in ser;
    ser.sin_family = AF_INET;
    ser.sin_port = htons(port);
    ser.sin_addr.s_addr = inet_addr(ip);
    int ret = bind(sockfd,(struct sockaddr *)&ser,sizeof(ser));
    if(ret == -1)
    {
        perror("fail bind");
        return -1;
    }
    ret = listen(sockfd,120);
    if(ret ==-1)
    {
        return -1;
    }
    return sockfd;
}
int main(int agrc,char *agrv[])
{
    int connfd = 0;
    char buf[1024] = {0};
    int ret;
    pthread_t tid ;
    int sockfd = conct("192.168.1.112",60000);
    if(sockfd == -1)
    {
        return -1;
    }
    while(1)
    {
        connfd = accept(sockfd,NULL,NULL);
        if(-1 == connfd)
        {
            return -1;
        }
        pthread_create(&tid,NULL,doSth,&connfd);
        pthread_detach(tid);
    }
    return 0;
 
}
3.3、IO多路复用

多个读写复用一个进程(在Linux里面就是文件读写)

四、IO模型
4.1、阻塞IO

fgets,scanf,read,recv,getchar(用来实现多个IO同步的效果)

同步:具有先后顺序的效果

#include<head.h>
 
int main(int agrc,char *agrv[])
{
    char buf[1024] = {0};
    mkfifo("./fifo",0666);
    int fd = open("./fifo",O_RDONLY);
   int flag =  fcntl(0,F_GETFL);
    flag = flag & ~O_NONBLOCK;
    fcntl(0,F_SETFL,flag);
    while(1)
    {
        memset(buf,0,sizeof(buf));
        fgets(buf,sizeof(buf),stdin);
        printf("STDIN : %s\n",buf);
        memset(buf,0,sizeof(buf));
        read(fd,buf,sizeof(buf));
        printf("buf = %s\n",buf);
    }
    close(fd);
    return 0;
}

特点:

  • CPU 占有率低
  • 执行效率低
4.2、非阻塞IO

非阻塞就是访问内核,有数据带着数据返回,没有数据也带着返回

特点 

  1. 使用轮询的方式实现
  2. CPU占有率高

 实现:

1、获取原文件描述符的属性

2、增加非阻塞属性

3、设置新属性

#include<head.h>
void handle(int signo)
{
    char buf[1024] = {0};
    fgets(buf,sizeof(buf),stdin);
    printf("STDIN : %s\n",buf);
}
int main(int agrc,char *agrv[])
{
    signal(SIGIO,handle);
    char buf[1024] = {0};
    mkfifo("./fifo",0666);
    int fd = open("./fifo",O_RDONLY);
    int flag = fcntl(0,F_GETFL);
    flag = flag | O_ASYNC;
    fcntl(0,F_SETFL,flag);
    fcntl(0,F_SETOWN,getpid());
    while(1)
    {
        memset(buf,0,sizeof(buf));
        read(fd,buf,sizeof(buf));
        sleep(1);
        printf("%s\n",buf);
    }
    close(fd);
    return 0;
}
4.3、信号驱动IO

实现:(当终端有输入的时候应该会触发,发射信号,才会执行)

1、增加异步属性  O_ASYNC(异步),O_SYNC(同步)

2、关联信号和当前的进程

3、注册信号

特点

1、异步通知io的方式,节省CPU

2、只能检测少量io

2、效率高

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值