用select实现多路IO复用

wrap.c多进程服务器-cainaiozjz

#include <stdio.h>
#include <sys/select.h>
#include <sys/types.h>
#include <unistd.h>
#include "wrap.h"
#include <sys/time.h>
#define SIZE  1024
#define PORT 8000
char *IP = "192.168.68.152";
// select多路IO复用
int main() 
{
    //创建监听套接字
    int lfd = Socket(AF_INET, SOCK_STREAM, 0);

    // 将监听套接字与IP:PORT绑定
    struct sockaddr_in s_addr;
    s_addr.sin_port = htons(PORT);
    s_addr.sin_family = AF_INET;
    inet_pton(AF_INET, "192.168.68.152", &s_addr.sin_addr.s_addr);
    socklen_t len = sizeof(s_addr);
    Bind(lfd, (struct sockaddr*)&s_addr, len);

    // 监听套接字开始监听
    Listen(lfd, 128);

    // 此时只有监听套接字需要select检查
    fd_set old_set, read_set;
    FD_ZERO(&old_set);
    FD_ZERO(&read_set);
    FD_SET(lfd, &old_set);
    int max_fd = lfd;
    while (1)
    {
        read_set = old_set;
        // 有文件描述符发生变化,select检查出
        int n = select(max_fd + 1, &read_set, NULL, NULL, NULL);

        if(-1 == n)
        {
            perror("select");
            return 1;
        }
        else if(0 == n)
            continue;
        
        // 先检查监听套接字是否有新连接
        if(FD_ISSET(lfd, &read_set))
        {
            struct sockaddr_in c_addr;
            int sfd = Accept(lfd, (struct sockaddr*)&c_addr, &len);
            FD_SET(sfd, &old_set);
            max_fd = sfd > max_fd ? sfd : max_fd;
            // 欢迎新连接
            char _ip[16] = "";
            printf("%s : %d连接成功\n", inet_ntop(AF_INET, &c_addr.sin_addr.s_addr, _ip, 16), 
                                        ntohs(c_addr.sin_port));
        }

        // 检查所有已连接的套接字
        for(int fd = lfd + 1; fd <= max_fd; ++fd)
        {
            if(FD_ISSET(fd, &read_set))
            {
                char buf[SIZE];
                bzero(buf, SIZE);
                int n = read(fd, buf, SIZE);
                if(n < 0) // read  出错
                {
                    perror("read");
                    close(fd);
                    FD_CLR(fd, &old_set);
                    if(fd == max_fd)
                        --max_fd;
                }
                else if(n == 0) // fd 套接字关闭, 在 oldset里置零
                {
                    FD_CLR(fd, &old_set);
                    close(fd);
                    printf("socket closed\n");
                    if(fd == max_fd)
                        --max_fd;
                }
                else          // 打印信息
                {
                    printf("%s\n", buf);
                    Write(fd, buf, n);
                }
            }
        }
    }
    
    return 0;
}
posted @ 2022-01-24 21:09  hellozhangjz  阅读(71)  评论(0)    收藏  举报