设为首页 加入收藏

TOP

IO多路复用(二) -- select、poll、epoll实现TCP反射程序(一)
2019-09-02 23:06:59 】 浏览:52
Tags:复用 select poll epoll 实现 TCP 反射 程序

接着上文IO多路复用(一)-- Select、Poll、Epoll,接下来将演示一个TCP回射程序,源代码来自于该博文https://www.cnblogs.com/Anker/p/3258674.html 博主的几篇相关的文章,在这里将其进行了整合,突出select、poll和epoll不同方法之间的比较,但是代码的结构相同,为了突出方法之间的差别,可能有的代码改动的并不合理,实际中使用并非这么写。

程序逻辑

该程序的主要逻辑如下:

服务器:
    1. 开启服务器套接字
    2. 将服务器套接字加入要监听的集合中(select的fd_set、poll的pollfd、epoll调用epoll_ctl)
    3. 进入循环,调用IO多路复用的API函数(select/poll/epoll_create),如果有事件产生:
        3.1. 服务器套接字产生的事件,添加新的客户端到监听集合中
        3.2. 客户端套接字产生的事件,读取数据,并立马回传给客户端
        
客户端:
    1. 开启客户端套接字
    2. 将客户端套接字和标准输入文件描述符加入要监听的集合中(select的fd_set、poll的pollfd、epoll调用epoll_ctl)
    3. 进入循环,调用IO多路复用的API函数(select/poll/epoll_create),如果有事件产生:
        3.1. 客户端套接字产生的事件,则读取数据,将其输出到控制台
        3.2. 标准输入文件描述符产生的事件,则读取数据,将其通过客户端套接字传给服务器

multiplexing.h

具体代码如下,首先是头文件

//multiplexing.h

#ifndef MULTIPLEXING_H
#define MULTIPLEXING_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <poll.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/epoll.h>
#include <unistd.h>
using namespace std;

#define MAXLINE     1024
class Multiplexing {
protected:
    static const int DEFAULT_IO_MAX = 10; //默认的最大文件描述符
    static const int INFTIM = -1;
    int io_max; //记录最大文件描述符
    int listenfd; //监听句柄
public:
    Multiplexing() { this->io_max = DEFAULT_IO_MAX; }
    Multiplexing(int max, int listenfd) { this->io_max = max; this->listenfd = listenfd; }
    ~Multiplexing() {}

    virtual void server_do_multiplexing() = 0; //服务端io多路复用
    virtual void client_do_multiplexing() = 0; //客户端io多路复用
    virtual void handle_client_msg() = 0; //处理客户端消息
    virtual bool accept_client_proc() = 0; //接收客户端连接
    virtual bool add_event(int confd, int event) = 0;
    virtual int wait_event() = 0; // 等待事件
};

//-----------------select-------------------------
class MySelect : public Multiplexing {
private:
    fd_set* allfds;      //句柄集合
    int* clifds;   //客户端集合
    int maxfd; //记录句柄的最大值
    int cli_cnt; //客户端个数

public:
    MySelect() : Multiplexing() { allfds = NULL; clifds = NULL; maxfd = 0; cli_cnt = 0; }
    MySelect(int max, int listenfd);
    ~MySelect() {
        if (allfds) {
            delete allfds;
            allfds = NULL;
        }
        if (clifds) {
            delete clifds;
            clifds = NULL;
        }
    }

    void server_do_multiplexing();
    void client_do_multiplexing();
    void handle_client_msg();
    bool accept_client_proc();
    bool add_event(int confd, int event);
    bool init_event(); //每次调用select前都要重新设置文件描述符
    int wait_event(); // 等待事件

};

//-----------------poll-------------------------
typedef struct pollfd Pollfd;
class MyPoll : public Multiplexing {
private:
    Pollfd* clientfds; //poll中使用pollfd结构体指定一个被监视的文件描述符
    int max_index; //记录当前clientfds数组中使用的最大下标

public:
    MyPoll() : Multiplexing() { clientfds = NULL; max_index = -1; }
    MyPoll(int max, int listenfd);
    ~MyPoll() {
        if (clientfds) {
            delete clientfds;
            clientfds = NULL;
        }
    }

    void server_do_multiplexing();
    void client_do_multiplexing();
    void handle_client_msg();
    bool accept_client_proc();
    bool add_event(int confd, int event);
    int wait_event(); // 等待事件
};

//-----------------epoll-------------------------
typedef struct epoll_event Epoll_event;
class MyEpoll : public Multiplexing {
private:
    int epollfd; //epoll的句柄,用来管理多个文件描述符
    Epoll_event *events; //事件数组
    int nready; //
首页 上一页 1 2 3 4 5 6 下一页 尾页 1/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇linux批量检测服务器能否ping通和.. 下一篇操作系统:进程的概念和与程序的..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目