【网络编程】poll实现IO多路复用

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

int main(int argc, char const *argv[])
{
    if (argc != 2)
    {
        perror("请输入端口号\n");
        return -1;
    }
    int sockfd,acceptfd;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (socket < 0)
    {
        perror("socket err");
        return -1;
    }
    printf("socket ok %d\n", sockfd);

    struct sockaddr_in serveraddr, caddr;
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(atoi(argv[1]));
    serveraddr.sin_addr.s_addr = INADDR_ANY;
    socklen_t len = sizeof(caddr);

    if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
    {
        perror("bind err");
        return -1;
    }
    printf("bind ok \n");

    if (listen(sockfd, 6) < 0)
    {
        perror("listen err");
        return -1;
    }
    printf("listen ok \n");

    //
    struct pollfd fds[20]={};//创建struct类型的文件描述符组,
    //填充组里边的数据
    fds[0].fd=0;//填写需要使用的文件
    fds[0].events=POLLIN;//设置检测事件为读事件
    //填充数据,类型同上
    fds[1].fd=sockfd;
    fds[1].events=POLLIN;
    //
    int ret;
    int n = 2;//文件描述符的个数,用于判断
    char buf[128];
    int recvbyte;
    while (1)//循环poll检测,poll阻塞等待有事件产生返回 -1
    {
        //阻塞,没有信号就不会进入循环
        ret=poll(fds,n,-1);
        if (ret<0)
        {
            perror("poll err\n");
            return -1;
        }

        for (int i = 0; i <n; i++)//循环监听
        {
            if (fds[i].revents == POLLIN)
            {

                if (fds[i].fd==0)//监听到描述符等于0执行
                {
                    fgets(buf,sizeof(buf),stdin);
                    printf("key:%s\n",buf);
                    for (int j = 2; j < n; j++)
                    {
                        send(fds[j].fd,buf,sizeof(buf),0);
                    }
                }
                else if (fds[i].fd == sockfd)//监听sockfd
                {
                    acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);
                    if (acceptfd<0)
                    {
                        perror("accept err\n");
                        return -1;
                    }
                    printf("accept ok\n");
                    printf("ip:%s ,post:%d\n",inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port));
                    fds[n].fd=acceptfd;//添加文件描述符,如果继续有人来链接,也可以监听到
                    fds[n].events=POLLIN;//设置状态
                    n++;
                }
                else
                {
                    recvbyte = recv(fds[i].fd,buf,sizeof(buf),0);
                    if (recvbyte<0)
                    {
                        perror("recv err\n");
                        return -1;
                    }
                    else if (recvbyte == 0)
                    {
                        printf("%d client exit\n",fds[i].fd);
                        
                        close(fds[i].fd);
                        fds[i]=fds[n-1];//客户端退出,文件描述符减少,文件描述符向前位移,执行前要先关闭
                        n--;//减去多余的位置
                        i--;
                        break;
                    }
                    else
                    {
                    printf("%d buf:%s\n",fds[i].fd,buf);
                    }
                }
            }
        }
    }
    close(sockfd);
    return 0;
}

重要的事说三遍,循环监听文件描述符,循环监听文件描述符,循环监听文件描述符

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值