epoll学习代码

服务端server

#include <head.h>

int setNonBlock(int fd)
{
    int status = 0;
    status = fcntl(fd, F_GETFL);
    
    status |= O_NONBLOCK;
    //把文件描述符设置为非阻性的
    fcntl(fd, F_SETFL, status);
    return 0;
}
int main(int argc, char** argv)
{
    //创建sfd,用于与客户端建立连接
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    ERROR_CHECK(sfd, -1, "socket");
    struct sockaddr_in serAddr;
    memset(&serAddr, 0, sizeof(serAddr));

    serAddr.sin_family = AF_INET;
    serAddr.sin_addr.s_addr = inet_addr(argv[1]);
    serAddr.sin_port = htons(atoi(argv[2]));

    //把sfd, 与本地的端口号和ip进行绑定
    int ret = bind(sfd, (struct sockaddr*)&serAddr, sizeof(serAddr));
    ERROR_CHECK(ret, -1, "bind");

    //监听sfd, 并且最大监听的连接数为10
    ret = listen(sfd, 10);
    ERROR_CHECK(ret, -1, "listen");

    //accept函数接收对端的连接请求,并且返回一个新的文件描述符,
    //新的文件描述符用于与对端进行数据的交互
    int newFd = 0;

    //创建epfd,用于管理
    int epfd = epoll_create(1);

    struct epoll_event event, evs[2];
    memset(&event, 0, sizeof(event));
    event.events = EPOLLIN;
    event.data.fd = STDIN_FILENO;
    //epoll_ctl把需要监听的文件描述符加入的epfd
    epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &event);

    event.data.fd = sfd;
    epoll_ctl(epfd, EPOLL_CTL_ADD, sfd, &event);

    int readyNum = 0;
    char buf[8] = {0};
    while(1){
        //epoll_wait会把就绪的文件描述符存储到evs中
        readyNum = epoll_wait(epfd, evs, 2, -1);
        printf("epoll_wait\n");
        for(int i = 0; i < readyNum; ++i){
            if(evs[i].data.fd == STDIN_FILENO){
                memset(buf, 0, sizeof(buf));
                read(STDIN_FILENO, buf, sizeof(buf));
                send(newFd, buf, strlen(buf)-1, 0);
            }
            if(evs[i].data.fd == newFd){
                while(1){
                    memset(buf, 0, sizeof(buf));
                    ret = recv(newFd, buf, sizeof(buf), 0);
                    //如果recv的返回值是0,就代表对端断开连接
                    if(0 == ret){
                        printf("bye,bye\n");
                        close(newFd);
                        continue;
                    }
                    //当recv是非阻塞的,没有接收到数据的时候会返回-1
                    if(-1 == ret){
                        break;
                    }
                    printf("buf = %s\n", buf);
                }
            }
            //如果sfd就绪就说明对端有连接请求,使用accept函数把
            //全连接队列里的第一个连接拿出来建立连接
            else if (evs[i].data.fd == sfd){
                newFd = accept(sfd, NULL, NULL);
                ERROR_CHECK(newFd, -1, "accept");
                //把newFd设置为非阻塞的
                setNonBlock(newFd);
                //把epoll的触发模式设置为边缘触发
                event.events = EPOLLIN|EPOLLET;
                event.data.fd = newFd;
                epoll_ctl(epfd, EPOLL_CTL_ADD, newFd, &event);
            }
        }
    }

    //关闭文件描述符
    close(sfd);
    close(newFd);
    return 0;
}

 

客户端client

#include <head.h>

int main(int argc, char** argv)
{
    //创建sfd描述符,用于与对端建立连接时使用
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    ERROR_CHECK(sfd, -1, "socket");
    
    struct sockaddr_in serAddr;
    memset(&serAddr, 0, sizeof(serAddr));

    serAddr.sin_family = AF_INET;
    serAddr.sin_addr.s_addr = inet_addr(argv[1]);
    serAddr.sin_port = htons(atoi(argv[2]));

    //连接服务器,把sfd与服务端的if与端口号建立连接
    int ret = connect(sfd, (struct sockaddr*)&serAddr, sizeof(serAddr));
    ERROR_CHECK(ret, -1, "connect");

    send(sfd, "hellocserver", 11, 0);

    char buf[128] = {0};
    //创建集合用于存储文件描述符
    fd_set rdset;
    FD_ZERO(&rdset);
    int readyNum = 0;
    //循环聊天
    while(1){
        //把需要监听的文件描述符加入到集合当中
        FD_SET(STDIN_FILENO, &rdset);
        FD_SET(sfd, &rdset);
        readyNum = select(sfd+1, &rdset, NULL, NULL, NULL);
        for(int i = 0; i < readyNum; ++i){
            //如果是标准输入就绪就发送数据
            if(FD_ISSET(STDIN_FILENO, &rdset)){
                memset(buf, 0, sizeof(buf));
                read(STDIN_FILENO, buf, sizeof(buf));
                send(sfd, buf, strlen(buf)-1, 0);
            }
            //如果是newFd就绪,说明对端有数据发送过来,就接收数据
            if(FD_ISSET(sfd, &rdset)){
                memset(buf, 0, sizeof(buf));
                recv(sfd, buf, sizeof(buf), 0);
                printf("buf = %s\n", buf);
            }
        }
    }

    close(sfd);
    return 0;
}

 

epoll学习代码

上一篇:MS Report踩坑与 /reporting/2016/01/reportdefinition cannot be upgraded 解决方案


下一篇:Transformer原理理解