高性能分布式网络服务器--Socket模块

Socket模块

上一章我们将网络编程使用频率非常高的地址封装到了Address模块中,但是Berkeley套接字接口也是非常多,并且属于面向过程编程。为了进一步降低网络编程门槛,我们将套接字涉及的接口和状态封装到一个对象中。Socket模块因此诞生。

github

https://github.com/huxiaohei/tiger.git

实现

  • Socket保存了套接字如下信息
    • 文件描述符m_sock
    • 地址类型m_familyAF_INETAF_INET6
    • 套接字类型(SOCK_STREAMSOCK_DGRAM
    • 是否链接m_is_connected
    • 本地地址m_local_addr
    • 远程地址m_remote_addr
  • Socket提供如下方法
    • 提供快速创建各种类型的套接字对象的方法
    • 设置套接字选项,比如超时等
    • 实现绑定地址bind、发起连接cinnect、监听listen、关闭close功能
    • 实现accept方法返回Socket对象
    • 实现套接字对象发送、接收消息
    • 提供套接字取消读写以及取消accept接口
  • Socket借助我们前面实现的FDManagerIOManagerHook等模块,让同步代码实现异步能力
class Socket : public std::enable_shared_from_this<Socket> {
   protected:
    int m_sock;
    int m_family;
    int m_type;
    int m_protocol;
    bool m_is_connected;
    Address::ptr m_local_addr;
    Address::ptr m_remote_addr;

   protected:
    virtual bool init(int sock);
    void init_sock();
    void new_sock();
    Address::ptr init_local_address();
    Address::ptr init_remote_address();

   public:
    typedef std::shared_ptr<Socket> ptr;

    Socket(int family, int type, int protocol = 0);
    virtual ~Socket();

    Socket(const Socket &) = delete;
    Socket(const Socket &&) = delete;
    Socket &operator=(const Socket &) = delete;

   public:
    static Socket::ptr CreateTCP(tiger::Address::ptr address);
    static Socket::ptr CreateUDP(tiger::Address::ptr address);
    static Socket::ptr CreateTCPSocket();
    static Socket::ptr CreateUDPSocket();
    static Socket::ptr CreateTCPSocket6();
    static Socket::ptr CreateUDPSocket6();
    static Socket::ptr CreateUnixTCPSocket();
    static Socket::ptr CreateUnixUDPSocket();

   public:
    int get_family() const { return m_family; }
    int get_type() const { return m_type; }
    int get_protocol() const { return m_protocol; }
    bool is_connected() const { return m_is_connected; }
    bool is_valid() const { return m_sock != -1; }
    int get_socket() const { return m_sock; }
    virtual std::ostream &dump(std::ostream &os) const;
    virtual std::string to_string() const;

   public:
    int get_error();
    int64_t get_send_timeout();
    void set_send_timeout(int64_t timeout);
    int64_t get_recv_timeout();
    void set_recv_timeout(int64_t timeout);
    Address::ptr get_local_addr();
    Address::ptr get_remote_addr();
    bool get_option(int level, int optname, void *optval, socklen_t *optlen);
    bool set_option(int level, int optname, const void *optval, socklen_t optlen);

    virtual bool connect(const Address::ptr addr, uint64_t timeout_ms = -1);
    virtual bool reconnect(const uint64_t timeout_ms = -1);

    virtual bool bind(const Address::ptr addr);
    virtual bool listen(int backlog = SOMAXCONN);
    virtual Socket::ptr accept();
    virtual bool close();

    virtual int send(const void *buffer, size_t len, int flags = 0);
    virtual int send(const iovec *buffers, size_t len, int flags = 0);

    virtual int send_to(const void *buffer, size_t len, const Address::ptr to, int flags = 0);
    virtual int send_to(const iovec *buffers, size_t len, const Address::ptr to, int flags = 0);

    virtual int recv(void *buffer, size_t len, int flags = 0);
    virtual int recv(iovec *buffers, size_t len, int flags = 0);

    virtual int recv_from(void *buffer, size_t len, Address::ptr from, int flags = 0);
    virtual int recv_from(iovec *buffers, size_t len, Address::ptr from, int flags = 0);

   public:
    bool cancel_read();
    bool cancel_write();
    bool cancel_accept();
    bool cancel_all();

   public:
    friend std::ostream &operator<<(std::ostream &os, const Socket::ptr socket);
    friend std::ostream &operator<<(std::ostream &os, const Socket &socket);
};

有了以上一系列模块的实现,我们网络编程会变的相对简单很多

void test_socket_send(const std::string &host, tiger::IOManager::ptr iom) {
    tiger::IPAddress::ptr addr = tiger::IPAddress::LookupAny(host);
    tiger::Socket::ptr socket = tiger::Socket::CreateTCPSocket();
    if (!socket->connect(addr)) {
        TIGER_LOG_E(tiger::TEST_LOG) << "[socket connnect fail errno:" << strerror(errno) << "]";
        return;
    }
    const char buffer[] = "GET / HTTP/1.0\r\n\r\n";
    ssize_t rt = socket->send(buffer, sizeof(buffer));
    if (rt <= 0) {
        TIGER_LOG_E(tiger::TEST_LOG) << "[socket send fail connected:" << socket->is_connected()
                                     << " errno:" << strerror(errno) << "]";
        return;
    }
    std::string buffs;
    buffs.resize(4096);
    rt = socket->recv(&buffs[0], buffs.size());
    if (rt <= 0) {
        TIGER_LOG_E(tiger::TEST_LOG) << "socket recv fail connected:" << socket->is_connected()
                                     << " errno:" << strerror(errno) << "]";
        return;
    }
    buffs.resize(rt);
    TIGER_LOG_D(tiger::TEST_LOG) << "socket recv:" << buffs;
    iom->stop();
}

int main() {
    tiger::SingletonLoggerMgr::Instance()->add_loggers("tiger", "../conf/tiger.yml");
    tiger::Thread::SetName("Socket");
    TIGER_LOG_D(tiger::TEST_LOG) << "[socket test start]";
    tiger::IOManager::ptr iom = std::make_shared<tiger::IOManager>("Socket", true, 1);
    iom->schedule(std::bind(test_socket_send, "www.baidu.com:80", iom));
    iom->start();
    TIGER_LOG_D(tiger::TEST_LOG) << "[socket test end]";
}

虽然网络编程门槛有所降低,但是还远远没有结束。进一步封装我们留到下一章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

虎小黑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值