用epoll()实现并发服务器通信

服务器端代码

#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/epoll.h>

int main(){

    //创建socket
    int lfd = socket(PF_INET,SOCK_STREAM,0);
    struct sockaddr_in saddr;
    saddr.sin_port = htons(9999);
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = INADDR_ANY;

    //绑定
    bind(lfd,(struct sockaddr*)&saddr,sizeof(saddr));

    //监听
    listen(lfd,8);

    //调用epoll_creat()创建一个epoll实例
    int epfd = epoll_create(100);

    //将监听的文件描述符添加到epoll实例的rbr中
    struct epoll_event epev;
    epev.events = EPOLLIN;
    epev.data.fd = lfd;
    epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&epev);

    struct epoll_event epevs[1024];

    while(1){
        int ret = epoll_wait(epfd,epevs,1024,-1);
        if(ret == -1){
            perror("epoll_wait");
            exit(-1);
        }
        // printf("ret = %d\n",ret);//将客户端中sleep(1)改为usleep(1000)可以看到ret = 2
        for(int i = 0; i < ret; i++){
            if(epevs[i].data.fd == lfd){
                //监听的文件描述符,有客户端连接
                struct sockaddr_in caddr;
                int len = sizeof(caddr);
                int cfd = accept(lfd,(struct sockaddr*)&caddr,&len);
                
                char cIp[32];
                printf("有新客户端连接,IP : %s,port : %d\n",
                    inet_ntop(AF_INET,&caddr.sin_addr.s_addr,cIp,sizeof(cIp)),
                    ntohs(caddr.sin_port));

                epev.events = EPOLLIN;//epev.events = EPOLLIN | EPOLLOUT
                epev.data.fd = cfd;
                epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&epev);
            }else{
                if(epevs[i].events & EPOLLOUT){//检测的有写入数据
                    continue;
                }
                //检测到有读数据到达,需要通信
                char buf[1024] = {0};
                int len = read(epevs[i].data.fd,buf,sizeof(buf));
                if(len == -1){
                    perror("read");
                    exit(-1);
                }else if(len == 0){
                    printf("client closed...");
                    close(epevs[i].data.fd);
                    epoll_ctl(epfd,EPOLL_CTL_DEL,epevs[i].data.fd,NULL);
                }else if(len > 0){
                    printf("read buf: %s\n",buf);
                    write(epevs[i].data.fd,buf,strlen(buf)+1);
                }
            }
        }
    }
    close(lfd);
    close(epfd);
    return 0;
}

客户端代码

//客户端
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int main(){

    //创建套接字
    int fd = socket(AF_INET,SOCK_STREAM,0);
    if(fd == -1){
        perror("socket");
        exit(-1);
    }

    //连接服务器
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    inet_pton(AF_INET,"192.168.245.128",&saddr.sin_addr.s_addr);
    saddr.sin_port = htons(9999);
    int ret = connect(fd,(struct sockaddr*)&saddr,sizeof(saddr));
    if(ret == -1){
        perror("connect");
        exit(-1);
    }

    //通信
    char recvBuf[1024] = {0};
    int i = 0;
    while(1){
        sprintf(recvBuf,"data : %d\n",i++);
        write(fd,recvBuf,strlen(recvBuf));

        int len = read(fd,recvBuf,sizeof(recvBuf));
        if(len == -1){
            perror("read");
            exit(-1);
        }else if(len > 0){
            printf("recv server data : %s\n",recvBuf);
        }else if(len == 0){
            printf("server closed...");
            break;
        }
        //sleep(1);
        usleep(1000);
    }
    return 0;
}

运行效果图
服务端

客户端1

客户端2

posted @   daydayupzgz  阅读(164)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示