Linux c++ poll 模型

来源:互联网 发布:linux telnet 安装 编辑:程序博客网 时间:2024/06/05 23:54

部分代码复用select的代码

主代码如下:

#include <unistd.h>#include <sys/types.h>#include <fcntl.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <signal.h>#include <sys/wait.h>#include <poll.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <vector>#include <iostream>#include "socket.h"typedef std::vector<struct pollfd> POLL_FD_VECTOR;int AcceptConnect(POLL_FD_VECTOR &PollFdVector){    struct sockaddr_in stPeerAddr;      struct pollfd stPollFd;      socklen_t SocketLen = 0;    int AcceptFd = -1;    //为什么是第0号元素?    //0号元素是server的 listen socket,用来侦听客户端连接    if (PollFdVector[0].revents & POLLIN)    {        SocketLen = sizeof(stPeerAddr);        AcceptFd = accept4(PollFdVector[0].fd, (struct sockaddr*)&stPeerAddr,                    &SocketLen, SOCK_NONBLOCK | SOCK_CLOEXEC);        if (AcceptFd == -1)        {        //进程打开描述符到达上限处理            if (errno == EMFILE)            {                ERR_INFO_S stErrInfo;                stErrInfo.enErrType = ERR_EMFILE;                stErrInfo.pvUserData = (void *)&AcceptFd;                ProcessErr(stErrInfo);                continue;            }            SHOW_ERR("\n");            goto EXIT;        }        else        {            // 连接成功            SHOW_SOCKADDR_INFO(stPeerAddr);            //将会话socket加入侦听序列            stPollFd.fd = AcceptFd;            stPollFd.events = POLLIN;            stPollFd.revents = 0;            PollFdVector.push_back(stPollFd);            goto EXIT;        }    }    else    {        return FAILURE;    }EXIT:    return SUCCESS;}int ReadData(POLL_FD_VECTOR &PollFdVector){    int s32Ret = -1;    int AcceptFd = -1;    //从1号元素开始轮询已经连接套接字事件,    for (POLL_FD_VECTOR::iterator it=PollFdVector.begin()+1;        it != PollFdVector.end(); ++it)    {            if (it->revents & POLLIN)            {                AcceptFd = it->fd;                char buf[NORMAL_BUF_LEN] = {0};                s32Ret = read(AcceptFd, buf, NORMAL_BUF_LEN);                if (s32Ret == -1)                {                    SHOW_ERR("\n");                }                if (s32Ret == 0)                {                    SHOW_ERR("client close!\n");                    it = PollFdVector.erase(it);                    --it;                    close(AcceptFd);                    continue;                }                std::cout<<buf;                write(AcceptFd, buf, strlen(buf));            }    }    return SUCCESS;}int main(void){    InitErrDeal();    int s32Ret = FAILURE;    int s32ServerFd = -1;    s32Ret = InitServerSocket(s32ServerFd);    {        SHOW_ERR("\n");    }//将监听socket加入侦听序列    struct pollfd stPollFd;      stPollFd.fd = s32ServerFd;    //events保存用户关注的事件标识    //revents保存内核侦听到的事件标识    stPollFd.events = POLLIN;    stPollFd.revents = 0;    POLL_FD_VECTOR PollFdVector;    PollFdVector.push_back(stPollFd);//侦听主循环    int s32ReadyNum = 0;    while (1)    {        s32ReadyNum = poll(&*PollFdVector.begin(), PollFdVector.size(), -1);        if (s32ReadyNum == -1)        {            if (errno == EINTR)            {                continue;            }            SHOW_ERR("\n");        }        else if (s32ReadyNum == 0)  // timeout        {            continue;        }        s32Ret = AcceptConnect(PollFdVector);        if(SUCCESS == s32Ret)        {            s32ReadyNum -- ;            if(0 == s32ReadyNum)            {                continue;            }        }        ReadData(PollFdVector);    }    return 0;}
原创粉丝点击