Linux网络编程—并发服务器

并发服务器:服务起在同一时刻可以响应多个客户端的请求
一.多进程

#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<string.h>
#include<sys/wait.h>

int tcp_init(const char *ip,int port)
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd == -1)
    {
        perror("socket fail");
        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 = bind(sockfd,(struct sockaddr *)&ser,sizeof(ser));
    if(ret_bind == -1)
    {
        perror("bind fail");
        return -1;
    }
    
    int ret_listen = listen(sockfd,10);
    if(ret_listen == -1)
    {
        perror("listen fail");
        return -1;
    }
    return sockfd;
}
void handle (int sig)
{
    wait(NULL);
}
int main(void)
{
    signal(SIGCHLD,handle);
    int sockfd = tcp_init("192.168.1.24",50000);
    if(sockfd == -1)
    {
        return -1;
    }

    while(1)
    {
        int accfd = accept(sockfd,NULL,NULL);
        if(accfd == -1)
        {
            perror("accept fail");
            return -1;
        }
        pid_t pid = fork();
        if(pid > 0)
        {
        
        }
        else if(pid == 0)
        {
            char buff[1024] = {0};
            while(1)
            {
                memset(buff,0,sizeof(buff));
                ssize_t size = recv(accfd,buff,sizeof(buff),0);
                if(size <= 0)
                {
                    break;
                }
                printf("buff=%s\n",buff);
                size = send(accfd,"HELLO",5,0);
                if(size < 0)
                {
                    break;
                }
            }
        }
        close(accfd);
    }
    close(sockfd);
    return 0;
}

二.多线程

#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<string.h>
#include<pthread.h>

int tcp_init(const char *ip,int port)
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd == -1)
    {
        perror("socket fail");
        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 = bind(sockfd,(struct sockaddr *)&ser,sizeof(ser));
    if(ret_bind == -1)
    {
        perror("bind fail");
        return -1;
    }
    
    int ret_listen = listen(sockfd,10);
    if(ret_listen == -1)
    {
        perror("listen fail");
        return -1;
    }
    return sockfd;
}
void *thread(void *arg)
{
    int accfd = *(int *)arg;
    char buff[1024] = {0};
    while(1)
    {
        memset(buff,0,sizeof(buff));
        ssize_t size = recv(accfd,buff,sizeof(buff),0);
        if(size <= 0)
        {
            break;
        }
        printf("buff=%s\n",buff);
        size = send(accfd,"HELLO",5,0);
        if(size < 0)
        {
            break;
        }
    }
    close(accfd);
}
int main(void)
{
    int sockfd = tcp_init("192.168.1.24",50000);
    if(sockfd == -1)
    {
        return -1;
    }
    
    pthread_t tid;

    while(1)
    {
        int accfd = accept(sockfd,NULL,NULL);
        if(accfd == -1)
        {
            perror("accept fail");
            return -1;
        }
        pthread_create(&tid,NULL,thread,&accfd);
        pthread_detach(tid);
    }
    
    close(sockfd);
    return 0;
}


三.IO多路复用
  1.select

 缺点:
         1.select监听文件描述符最大个数为1024    (数组)    
         2.select监听的文件描述符集合在用户层,需要应用层和内核层互相传递数据
         3.select需要循环遍历一次才能找到产生的事件
         4.select只能工作在水平触发模式(低速模式)无法工作在边沿触发模式(高速模式)
            
 2.poll
         
缺点:
         1.poll监测文件描述符不受上限限制  (链表)
         2.poll监听的文件描述符集合在用户层,需要内核层向用户层传递数据
         3.poll需要循环遍历一次才能找到产生的事件
         4.poll只能工作在水平触发模式(低速模式)无法工作在边沿触发模式(高速模式)
        
 3.epoll
         
优点:
        1.epoll创建内核事件表,不受到文件描述符上限限制    (红黑树)        
        2.epoll监听的事件表在内核中,直接在内核中监测事件效率高
        3.epoll会直接获得产生事件的文件描述符的信息,而不需要遍历检测 
        4.epoll既能工作在水平触发模式,也能工作在边沿触发模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值