简单的客户端服务器以及poll epoll的使用
发布日期:2021-05-08 05:02:51 浏览次数:19 分类:原创文章

本文共 7447 字,大约阅读时间需要 24 分钟。

一、简单的客户端
创建socket连接服务器 connect收发数据 read write

#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>

#include <stdlib.h>
#include <stdio.h>
#include <error.h>
#include <string.h>

#include
#include

#define ERR_EXIT(m)
do
{
perror(m);
exit(EXIT_FAILURE);
}while(0)

typedef std::vector PollFdList;

int main(void)
{

int clientfd;if((clientfd = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0)    ERR_EXIT("socket");//CLOEXEC FORK进程时文件描述符处于关闭状态struct sockaddr_in servaddr;memset(&servaddr,0,sizeof (servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(5188);servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");if(connect(clientfd,(struct sockaddr*)&servaddr,sizeof (servaddr))<0)    ERR_EXIT("connect");struct sockaddr_in localaddr;socklen_t addrlen = sizeof(localaddr);if(getsockname(clientfd,(struct sockaddr*)&localaddr,&addrlen)<0)    ERR_EXIT("getsockname");std::cout<<"ip="<<inet_ntoa(localaddr.sin_addr)<<          "port="<<ntohs(localaddr.sin_port)<<std::endl;char sendbuf[1024] = {0};char recvbuf[1024] = {0};while(fgets(sendbuf,sizeof (sendbuf),stdin)!=NULL){    write(clientfd,sendbuf,strlen(sendbuf));    read(clientfd,recvbuf,sizeof (recvbuf));    fputs(recvbuf,stdout);    memset(sendbuf,0,sizeof (sendbuf));    memset(recvbuf,0,sizeof (recvbuf));}close(clientfd);return 0;

}
二、简单的服务器
在这里插入图片描述
1、poll 服务器
#include <unistd.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 <error.h>
#include <string.h>

#include
#include

#define ERR_EXIT(m)
do
{
perror(m);
exit(EXIT_FAILURE);
}while(0)

typedef std::vector PollFdList;

int main(void)
{
signal(SIGPIPE,SIG_IGN);//客户端主动关闭产生,服务器write
//TIME——WAIT状态 服务器主动断开连接,服务器就会进入TIME_WAIT
signal(SIGCHLD,SIG_IGN);//子进程关闭

int listenfd;if((listenfd = socket(PF_INET,SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC,IPPROTO_TCP))<0)    ERR_EXIT("socket");//CLOEXEC FORK进程时文件描述符处于关闭状态struct sockaddr_in servaddr;memset(&servaddr,0,sizeof (servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(5188);servaddr.sin_addr.s_addr = htonl(INADDR_ANY);int on = 1;if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof (on))<0)    ERR_EXIT("setsockopt");if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof (servaddr))<0)    ERR_EXIT("bind");if(listen(listenfd,SOMAXCONN)<0)    ERR_EXIT("listen");std::cout<<"server is running"<<std::endl;struct pollfd pfd;pfd.fd = listenfd;pfd.events = POLLIN;PollFdList pollfds;pollfds.push_back(pfd);int nready;struct sockaddr_in peeraddr;socklen_t peerlen;int connfd;while(1){    nready=poll(&*pollfds.begin(),pollfds.size(),-1);    if(nready==-1)    {        if(errno == EINTR)            continue;        ERR_EXIT("poll");    }    if(nready==0)        continue;    if(pollfds[0].revents & POLLIN)    {        peerlen = sizeof(peeraddr);        connfd = ::accept4(listenfd,(struct sockaddr*)&peeraddr,&peerlen,SOCK_NONBLOCK|SOCK_CLOEXEC);        if(connfd==-1)            ERR_EXIT("accept4");        pfd.fd = connfd;        pfd.events = POLLIN;        pfd.revents = 0;        pollfds.push_back(pfd);        std::cout<<"ip="<<inet_ntoa(peeraddr.sin_addr)<<"port="<<ntohs(peeraddr.sin_port)<<std::endl;    }    //std::cout<<pollfds.size()<<std::endl;    //std::cout<<nready<<std::endl;    for(PollFdList::iterator it = pollfds.begin()+1;it!=pollfds.end()&&nready>0;++it)    {        if(it->revents & POLLIN)        {            --nready;            connfd = it->fd;            char buf[1024] = {0};            int ret =read(connfd,buf,1024);            if(ret==-1)                ERR_EXIT("read");        if(ret==0)        {            std::cout<<"client:close"<<std::endl;            it=pollfds.erase(it);            --it;            close(connfd);            continue;        }        std::cout<<buf;        write(connfd,buf,strlen(buf));        }    }}return 0;

}

2、epoll 服务器

#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <error.h>
#include <string.h>

#include
#include

#define ERR_EXIT(m)
do
{
perror(m);
exit(EXIT_FAILURE);
}while(0)

typedef std::vector EventList;

int main(void)
{
signal(SIGPIPE,SIG_IGN);//客户端主动关闭产生,服务器write
//TIME——WAIT状态 服务器主动断开连接,服务器就会进入TIME_WAIT
signal(SIGCHLD,SIG_IGN);//子进程关闭

int listenfd;if((listenfd = socket(PF_INET,SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC,IPPROTO_TCP))<0)    ERR_EXIT("socket");//CLOEXEC FORK进程时文件描述符处于关闭状态struct sockaddr_in servaddr;memset(&servaddr,0,sizeof (servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(5188);servaddr.sin_addr.s_addr = htonl(INADDR_ANY);int on = 1;if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof (on))<0)    ERR_EXIT("setsockopt");if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof (servaddr))<0)    ERR_EXIT("bind");if(listen(listenfd,SOMAXCONN)<0)    ERR_EXIT("listen");std::cout<<"server is running"<<std::endl;std::vector<int> clients;int epollfd;epollfd = epoll_create1(EPOLL_CLOEXEC);struct epoll_event event;event.data.fd = listenfd;event.events = EPOLLIN;/*EPOLLET*/epoll_ctl(epollfd,EPOLL_CTL_ADD,listenfd,&event);EventList events(16);int nready;struct sockaddr_in peeraddr;socklen_t peerlen;int connfd;while(1){    nready=epoll_wait(epollfd,&*events.begin(),static_cast<int>(events.size()),-1);    if(nready==-1)    {        if(errno == EINTR)            continue;        ERR_EXIT("epoll_wait");    }    if(nready==0)        continue;    if((size_t)nready==events.size())        events.resize(events.size()*2);    for(int i=0;i<nready;i++)    {        if(events[i].data.fd==listenfd)        {            peerlen = sizeof (peeraddr);            connfd = ::accept4(listenfd,(struct sockaddr*)&peeraddr,&peerlen,SOCK_NONBLOCK|SOCK_CLOEXEC);            if(connfd==-1)            {                if(errno==EMFILE)                {                     int idlefd;                     idlefd = accept(listenfd,NULL,NULL);                     close(idlefd);                     idlefd = open("/dev/null",O_RDONLY|O_CLOEXEC);                     continue;                }                else                    ERR_EXIT("accept4");            }            std::cout<<"ip="<<inet_ntoa(peeraddr.sin_addr)<<"port="<<ntohs(peeraddr.sin_port)<<std::endl;            clients.push_back(connfd);            event.data.fd = connfd;            event.events = EPOLLIN;            epoll_ctl(epollfd,EPOLL_CTL_ADD,connfd,&event);        }        else if(events[i].events & EPOLLIN)        {            connfd = events[i].data.fd;            if(connfd<0)                continue;            char buf[1024]={0};            int ret = read(connfd,buf,1024);            if(ret==-1)                ERR_EXIT("read");            if(ret==0)            {                std::cout<<"client close"<<std::endl;                close(connfd);                event = events[i];                epoll_ctl(epollfd,EPOLL_CTL_DEL,connfd,&event);                for(std::vector<int>::iterator it=clients.begin();it!=clients.end();it++)                {                    if(*it==event.data.fd)                    {                        clients.erase(it);                        break;                    }                }                continue;            }            std::cout<<buf;            write(connfd,buf,strlen(buf));        }    }}return 0;

}

上一篇:gdb调试命令的使用及总结
下一篇:deepin 15.11 Qt无法使用中文输入法解决办法

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2025年04月11日 00时10分43秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章