c++封装Rector

最近看了《linux高性能服务器编程》那本书, 上面描述Rector的一张图
这里写图片描述

对着这图,自己用c++封装了一下, 不知道有什么不足出,请大神们多多指点下。代码如下:
服务器端代码:

#include <iostream>
#include <unistd.h>
#include <cassert>
#include <cstdlib>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <vector>
#include <map>
#include <fcntl.h>

using namespace std;
#define MAX 100
int listenfd;
class Rector;
class Demultiplexer;
class Handle
{
public:
    Handle(int fd = -1): m_fd(fd) {}
    virtual ~Handle() {close(m_fd);}
    virtual void call_back(int fd){}
    int getfd() const
    {
        return m_fd;
    }
protected:
    int m_fd;
};

class TcpHandle : public Handle
{
public:
    TcpHandle(int fd) : Handle(fd) {}
    void call_back(int fd)
    {
        char buff[1024] = {0};
        memset(buff, 0, 1024);
        int n = recv(fd, buff, 1024, 0);
        if(n < 0)
            perror("recv error");
        else if(n == 0)
             cout << "one client over " << endl;
        else
            cout << "recv data: " << buff << endl;
        send(fd, "OK", 2, 0);
    }   
};

class Demultiplexer
{
public:
    Demultiplexer(int fd = -1) : epfd(fd){}
    ~Demultiplexer(){close(epfd);}

    void Register(Handle* handle);
    void Remove(Handle* handle);
    void dispatch();
    void start_listen(int fd, char *ip, int port);

private:
    map<int, Handle*> m_dump;
    int epfd;
    struct epoll_event fds[MAX];
};

void Demultiplexer::start_listen(int fd, char *ip, int port)
{
    epfd = epoll_create(MAX);
    struct sockaddr_in saddr;
    memset(&saddr, 0, sizeof(saddr));

    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(port);
    saddr.sin_addr.s_addr = inet_addr(ip);

    assert(bind(fd, (struct sockaddr*)&saddr, sizeof(saddr)) != -1);

    assert(listen(fd, 5) != -1);
}

void Demultiplexer::Register(Handle* handle)
{
    int fd = handle->getfd();
    struct epoll_event ev;
    ev.events = EPOLLIN | EPOLLET;
    ev.data.fd = fd;

    if(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1)
    {
        perror("epoll_ctl error");
        return ;
    }

    int oldflag = fcntl(fd, F_GETFL);
    int newflag = oldflag | O_NONBLOCK;

    if(fcntl(fd, F_SETFL, newflag) == -1)
    {
        perror("fcntl error");
        return ;
    }

    m_dump.insert(make_pair(fd, handle));
}

void Demultiplexer::Remove(Handle* handle)
{
    int fd = handle->getfd();
    if(epoll_ctl(epfd, EPOLL_CTL_DEL,fd, NULL) == -1)
    {
        perror("epoll_ctr error");
    }

    m_dump.erase(fd);
}

void Demultiplexer::dispatch()
{

    while(1)
    {
        int n = epoll_wait(epfd, fds, MAX, -1);
        switch(n)
        {
        case -1:
            perror("epoll_wait error");
        break;
        case 0:
            continue;
        break;
        default:
            {
                for(int i = 0; i < n; ++i)
                {
                    if(fds[i].data.fd == listenfd)
                    {
                        struct sockaddr_in caddr;
                        socklen_t len = sizeof(caddr);
                        int c = accept(fds[i].data.fd, (struct sockaddr*)&caddr, &len);

                        cout << "one client connect ip: " << inet_ntoa(caddr.sin_addr) << " port: "
                        << ntohs(caddr.sin_port) << endl;
                        Handle *p = new TcpHandle(c);
                        Register(p);
                    }
                    else if(fds[i].events & EPOLLIN)
                    {
                        int fd = fds[i].data.fd;
                        map<int, Handle*>::iterator it = m_dump.find(fds[i].data.fd);
                        if(it != m_dump.end())
                        {
                            (it->second)->call_back(fd);
                        }
                        else
                        {
                            m_dump.erase(fd);
                            Remove(new TcpHandle(fd));
                        }
                    }
                }
            }
            break;
        }
    }
}

class Rector
{
public:
    static Rector* getInstance()
    {
        if(m_rector == NULL)
        {
            m_rector = new Rector();
        }

        return m_rector;
    }
    void start(int fd, char *ip, int port)
    {
        m_demp.start_listen(fd, ip, port);
    }
    void Register(Handle *handle)
    {
        m_demp.Register(handle);
    }
    void Remove(Handle* handle)
    {
        m_demp.Remove(handle);
    }
    void handle_event()
    {
        m_demp.dispatch();
    }
private:
    Rector(){}
    static Rector* m_rector;
    Demultiplexer m_demp;
};

Rector* Rector::m_rector = NULL;
static Rector* rector = Rector::getInstance();


int main(int argc, char* argv[])
{
    if(argc < 3)
    {
        cout << "invalid argument" << endl;
        exit(0);
    }

    int port = atoi(argv[2]);
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    assert(listenfd != -1);

    rector->start(listenfd, argv[1], port);
    Handle *p = new TcpHandle(listenfd);

    rector->Register(p);

    rector->handle_event();  //循环

    return 0;
}

客户端代码:

#include <iostream>
using namespace std;
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <cassert>
#include <sys/epoll.h>
#include <fcntl.h>
#include <stdio.h>
#include <cstdlib>
#include <errno.h>

class Client
{
public:
    Client(char *ip, int port)
    {
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        assert(sockfd != -1);

        struct sockaddr_in saddr;
        bzero(&saddr, sizeof(saddr));

        saddr.sin_family = AF_INET;
        saddr.sin_port = htons(port);
        saddr.sin_addr.s_addr = inet_addr(ip);
        socklen_t len = sizeof(saddr);

        setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &saddr, len);

        if(connect(sockfd, (struct sockaddr*)&saddr, len) < 0)
        {
            cout << errno << endl;
            perror("connect error");
        }
    }
    void sendData(char *buff) 
    {
        send(sockfd, buff, strlen(buff), 0);
    }
    void recvData(char *buff) 
    {
        recv(sockfd, buff, 1024, 0);
    }
    int getfd() const{
        return sockfd;
    }
private:
    int sockfd; 
};


int main(int argc, char *argv[])
{
    if(argc < 3)
    {
        cout << "Invalid argument !" << endl;
        exit(0);
    }
    int port = atoi(argv[2]);
    Client cli(argv[1], port);

    char buff[1024] = {0};

    while(1)
    {
        memset(buff, 0, 1024);
        cin.getline(buff, 1024);
        cli.sendData(buff);

        memset(buff, 0, 1024);
        cli.recvData(buff);
        cout << "recv data: " << buff << endl;
    }

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值