简单的客户端服务器以及poll epoll的使用

一、简单的客户端
创建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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值