利用C语言实现基于 poll的TCP回声服务器,可以高效地处理多个客户端连接,这种模型被称为多路复用。下面是一个精简而专业的指南,展示了如何通过 poll来实现这一目标。

关键概念

  • TCP服务器:一种在网络编程中常用的服务器模型,用于提供可靠的、面向连接的通信。
  • 回声服务器:这种服务器简单地将接收到的数据回发给发送者。
  • poll系统调用poll提供了一种方式,允许程序监视多个文件描述符集合中的事件,是多路复用编程的一种方式。

实现步骤

  1. 初始化服务器

    • 创建一个TCP套接字。
    • 将套接字绑定到服务器地址(IP地址和端口)。
    • 监听套接字,准备接受客户端连接。
  2. 设置 poll

    • 创建 pollfd结构体数组,以跟踪和管理多个套接字。
    • 将监听套接字加入到 pollfd数组中,设置相应的事件为 POLLIN,以表明我们对可读事件感兴趣。
  3. 事件循环

    • 使用 poll系统调用等待事件发生。poll调用将阻塞,直到一个或多个套接字准备好进行I/O操作。
    • 遍历 pollfd数组,检查哪些套接字有事件发生。

      • 如果监听套接字有事件发生,接受新的客户端连接,并将新的套接字添加到 pollfd数组中。
      • 如果是已连接的客户端套接字上有事件发生,读取数据并回发给客户端。如果读取到的数据长度为0(客户端关闭连接),则关闭套接字并从 pollfd数组中移除。
  4. 数据处理

    • 从活跃的客户端套接字读取数据。
    • 将接收到的数据原封不动地发送回客户端。
  5. 清理与资源管理

    • 一旦服务完成,关闭所有打开的套接字。
    • 确保在退出程序前释放所有分配的资源。

示例代码

下面是一个简化的示例代码,展示了如何使用 poll来实现多路复用的TCP回声服务器:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <poll.h>

#define MAX_CLIENTS 10
#define BUFFER_SIZE 1024

int main() {
    int sockfd, newsockfd, portno = 12345;
    struct sockaddr_in serv_addr, cli_addr;
    socklen_t clilen;
    struct pollfd fds[MAX_CLIENTS];
    int nfds = 1, current_size = 0, i, ret;
    char buffer[BUFFER_SIZE];

    // 创建TCP套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("ERROR opening socket");
        exit(1);
    }

    // 绑定到本地地址
    memset((char *)&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);

    if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        perror("ERROR on binding");
        exit(1);
    }

    // 监听
    listen(sockfd, 5);

    // 初始化pollfd结构
    memset(fds, 0 , sizeof(fds));
    fds[0].fd = sockfd;
    fds[0].events = POLLIN;

    // 循环等待
    while (1) {
        ret = poll(fds, nfds, -1);
        if (ret < 0) {
            perror("ERROR on poll");
            exit(1);
        }

        // 检查是否是新连接
        if (fds[0].revents & POLLIN) {
            clilen = sizeof(cli_addr);
            newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
            if (newsockfd < 0) {
                perror("ERROR on accept");
                continue;
            }
            fds[nfds].fd = newsockfd;
            fds[nfds].events = POLLIN;
            nfds++;
        }

        // 检查数据接收
        for (i = 1; i < nfds; i++) {
            if (fds[i].revents & POLLIN) {
                memset(buffer, 0, BUFFER_SIZE);
                ret = read(fds[i].fd, buffer, BUFFER_SIZE);
                if (ret < 0) {
                    perror("ERROR reading from socket");
                    close(fds[i].fd);
                    continue;
                } else if (ret == 0) {
                    close(fds[i].fd);
                    fds[i].fd = -1; // 标记为不用
                } else {
                    write(fds[i].fd, buffer, ret);
                }
            }
        }
    }

    close(sockfd);
    return 0;
}

此代码仅为示例,展示了如何基于 poll实现多路复用的TCP回声服务器的基本框架。在实际应用中,你可能需要对其进行扩展或修改,以满足具体的需求。

云服务器/高防CDN推荐

蓝易云国内/海外高防云服务器推荐


免备案五网CN2云服务器:www.tsyvps.com

蓝易云安全企业级高防CDN:www.tsycdn.com

持有增值电信营业许可证:B1-20222080【资质齐全】

蓝易云香港五网CN2 GIA/GT精品网络服务器。拒绝绕路,拒绝不稳定。

蓝易云是一家专注于香港及国内数据中心服务的提供商,提供高质量的服务器租用和云计算服务、包括免备案香港服务器、香港CN2、美国服务器、海外高防服务器、国内高防服务器、香港VPS等。致力于为用户提供稳定,快速的网络连接和优质的客户体验。
最后修改:2024 年 04 月 10 日
如果觉得我的文章对你有用,请随意赞赏