实现I/O多路复用并发服务器与客户端通信

网络编程实现通信时,通常是一个服务器处理多个客户端的请求,处理多个客户端请求时,服务器程序有不同的处理方式。比较常用的有循环服务器和并发服务器。

1、循环服务器:

循环服务器在同一时刻只能响应处理一个客户端的请求。

2、并发服务器:

并发服务器相比循环服务器,优点在于同一时刻服务器可以响应处理多个客户端的请求。

无论是TCP循环服务器还是UDP循环服务器,使用效率低而且使用范围较小,因此重点关注并发服务器实现通信。

多进程并发服务器

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define SIZE 64

int server_init(char *ipaddr, unsigned short port, int backlog)
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);     //创建网络通信接口
    if(-1 == sockfd)
    {
        perror("socket");
        return -1;
    }



    struct sockaddr_in saddr;      //服务器的地址结构
    bzero(&saddr,sizeof(saddr));   //saddr清0操作
    saddr.sin_family = AF_INET;    //指定协议族ipv4 
    saddr.sin_port = htons(port);  //端口号:5001~65535 
    saddr.sin_addr.s_addr = (ipaddr == NULL)? htonl(INADDR_ANY) : inet_addr(ipaddr);  
 //ip地址 点分式 -> 二进制网络字节序
    //saddr.sin_port.s_addr=inet_addr("127.0.0.1");ip回环地址
    
    int ret = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));    //绑定 将服务器的ip和port与sockfd绑定
    if(-1 == ret)
    {
        perror("bind");
        close(sockfd);   //关闭套接字
        return -1;
    }
    printf("bind success\n");   //绑定成功

    ret = listen(sockfd, backlog);     //监听是否有客户端请求连接 sockfd:监听套接字
    if(-1 == ret)
    {
        perror("listen");
        close(sockfd);
        return -1;
    }

    return sockfd;
}

void sighandler(int signo)     //自定义信号处理函数
{
    //回收子进程资源
    if(SIGCHLD==signo)
        
        while( waitpid(-1,NULL,WNOHANG)>0);   //循环回收资源
}

int main(int argc, char *argv[])
{
    if(argc < 3)
    {
        printf("Usage:%s  \n",argv[0]);   //参数输入提示
        return -1;
    }
    signal(SIGCHLD,sighandler);
    int sockfd = server_init(argv[1], atoi(argv[2]), 1024);    //调用函数
    if(-1 == sockfd)
    {
        printf("server_init error\n");
        return -1;
    }
    printf("listen....\n");
    char buf[64]={0};
    while(1)
    {
        struct sockaddr_in caddr;       //保存客户端的信息(ip port protocol)
        bzero(&caddr, sizeof(caddr));
        socklen_t clen = sizeof(caddr);

        


        //rws:用于服务器和连接的客户端通信
        int rws = accept(sockfd, (struct sockaddr *)&caddr, &clen);    //阻塞等待客户端请求连接
        if(-1 == rws)
        {
            perror("accept");
            close(sockfd);
            return -1;
        }

        //创建子进程
        pid_t pid=fork();
        if(pid==-1)
        {
            perror("fork");
            break;
        }
        else if(pid==0)
        {
            close(sockfd);     //关闭监听套接字
            while(1)
            {
                bzero(buf, sizeof(buf));

你可能感兴趣的:(服务器,c语言,网络协议,linux)