Socket编程权威指南(五)高性能 Socket 编程实战


在前几篇文章中,我们深入探讨了 Socket 编程的基础知识以及 I/O 复用模型。现在,是时候把这些理论付诸实践,构建一个真正的高性能网络应用了。本文将展示如何使用 C++ 编写模块化、可扩展的服务器和客户端程序,重点关注性能、可用性、安全性等关键方面,为你打造高水准的编码体验。


一、架构设计


在动手编码之前,我们先来规划一下程序的整体架构。

我们将分别实现一个服务器端类和客户端类,通过面向对象的设计模式,实现代码的模块化和可扩展性。

另外,服务器端将采用 I/O 复用模型,可以高效处理大量并发连接。

服务器端类的主要职责包括:

  • 初始化服务器套接字
  • 绑定地址
  • 监听连接请求
  • 接收连接
  • 读写数据

客户端类:

  • 负责创建客户端套接字

  • 连接服务器

  • 发送数据

  • 接收响应

为了提高程序的可用性,我们还需要在关键环节添加错误处理机制,确保意外情况下资源能安全回收,程序不会崩溃。

同时,通过使用 C++ 11 的现代语言特性,如 lambda 表达式、智能指针等,可以大幅增强代码的安全性和可读性。


二、服务器端实现


服务器端类的核心逻辑在于事件循环,它使用 poll() 函数监视套接字活动,高效地响应每一个就绪事件。

下面是服务器端类的框架代码:

class TcpServer {
public:
    TcpServer(const std::string& ip, int port)
        : m_ip(ip), m_port(port) {}

    void start() {
        // 初始化服务器套接字
        // ...

        while (true) {
            // 使用 poll() 监视套接字活动
            int nfds = ::poll(m_pollfds.data(), m_pollfds.size(), -1);
            if (nfds == -1) {
                // 处理错误
                continue;
            }

            // 处理就绪事件
            for (auto& pollfd : m_pollfds) {
                if (pollfd.revents & POLLIN) {
                    if (pollfd.fd == m_listensock) {
                        // 接受新连接
                    } else {
                        // 读取数据
                    }
                } else if (pollfd.revents & POLLOUT) {
                    // 发送数据
                }
            }
        }
    }

private:
    std::string m_ip;
    int m_port;
    int m_listensock;
    std::vector<pollfd> m_pollfds;
    // ...
};

在事件循环中,我们首先调用 poll() 函数获取就绪事件列表。

然后对每一个就绪事件进行处理,如果是监听套接字就绪,则接受新连接;如果是数据套接字就绪,则读取或发送数据。

接下来,我们来实现几个关键函数,包括初始化服务器套接字、接受连接以及读写数据等。

void TcpServer::init_server_socket() {
    m_listensock = ::socket(AF_INET, SOCK_STREAM, 0);
    if (m_listensock == -1) {
        // 处理错误
        return;
    }

    int opt = 1;
    ::setsockopt(m_listensock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(m_ip.c_str());
    addr.sin_port = htons(m_port);

    if (::bind(m_listensock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
        // 处理错误
        return;
    }

    if (::listen(m_listensock, SOMAXCONN) == -1) {
        // 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

w风雨无阻w

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

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

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

打赏作者

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

抵扣说明:

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

余额充值