c++ 单线程实现同时监听多个端口

要实现C++单线程同时监听多个端口,可以使用select和poll这两个系统调用。这两个函数都可以用来完成IO多路复用,允许开发者同时监视多个文件描述符的状态。以下是实现方法的详细攻略:

1. 创建套接字

在开始监听端口之前,需要先创建套接字。使用socket函数可以创建一个套接字,其中参数domain设置为AF_INET(IPv4地址族),type设置为SOCK_STREAM(面向连接的套接字),protocol设置为0。

int sock = socket(AF_INET, SOCK_STREAM, 0);

2. 绑定端口

创建套接字后,需要将其绑定到指定的端口上。使用bind函数可以将套接字绑定到本地IP地址和端口号上。需要填写sockaddr_in结构体,其中sin_family设置为AF_INET,sin_addr.s_addr设置为INADDR_ANY(表示所有IP地址),sin_port设置为要绑定的端口号。

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port);

int ret = bind(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
if (ret == -1) {
    perror("bind");
    exit(EXIT_FAILURE);
}

3. 监听端口

绑定端口后,套接字就已经准备好监听连接请求了。使用listen函数可以将套接字转换为监听状态,并指定可以同时接受的最大连接请求数。

int backlog = 20;
int ret = listen(sock, backlog);
if (ret == -1) {
    perror("listen");
    exit(EXIT_FAILURE);
}

4. 设置文件描述符集合

C++单线程同时监听多个端口需要用到select或poll函数。在使用这些函数前,需要先设置文件描述符集合。使用fd_set类型结构体表示文件描述符集合,可以使用宏FD_ZERO和FD_SET分别来初始化和添加文件描述符。

fd_set fds;
FD_ZERO(&fds);
FD_SET(sock1, &fds);
FD_SET(sock2, &fds);

5. 调用select或poll函数

设置文件描述符集合后,可以调用select或poll函数来监听文件描述符的状态。这些函数均具有超时功能,可以使用NULL表示阻塞直到有事件发生,或使用timeval类型结构体指定超时时间。

使用select函数

struct timeval tv;
tv.tv_sec = 10;
tv.tv_usec = 0;

int ret = select(1, &fds, NULL, NULL, &tv);
if (ret == -1) {
    perror("select");
    exit(EXIT_FAILURE);
} else if (ret == 0) {
    printf("timeout\n");
} else {
    if (FD_ISSET(sock1, &fds)) {
        // 处理sock1
    }
    if (FD_ISSET(sock2, &fds)) {
        // 处理sock2
    }
}

使用poll函数

int timeout = 10000;

int ret = poll(fds, 2, timeout);
if (ret == -1) {
    perror("poll");
    exit(EXIT_FAILURE);
} else if (ret == 0) {
    printf("timeout\n");
} else {
    if (fds[0].revents & POLLIN) {
        // 处理sock1
    }
    if (fds[1].revents & POLLIN) {
        // 处理sock2
    }
}

示例说明

示例1

使用select函数同时监听两个端口。一个端口用于接收TCP连接请求,另一个端口用于接收UDP数据包。

fd_set fds;
FD_ZERO(&fds);
FD_SET(tcp_sock, &fds);
FD_SET(udp_sock, &fds);

struct timeval timeout;
timeout.tv_sec = 30;
timeout.tv_usec = 0;

int ret = select(2, &fds, NULL, NULL, &timeout);
if (ret == -1) {
    perror("select");
    exit(EXIT_FAILURE);
} else if (ret == 0) {
    printf("timeout\n");
} else {
    if (FD_ISSET(tcp_sock, &fds)) {
        printf("tcp connection request\n");
        // 处理TCP连接请求
    }
    if (FD_ISSET(udp_sock, &fds)) {
        printf("udp data received\n");
        // 处理UDP数据包
    }
}

示例2

使用poll函数同时监听三个端口,其中一个端口用于接收GPIO信号。当GPIO输出电平变化时,会产生电平变化中断,这时需要通过该端口接受信号并执行相应操作。

struct pollfd fds[3];
fds[0].fd = tcp_sock;
fds[0].events = POLLIN;
fds[1].fd = udp_sock;
fds[1].events = POLLIN;
fds[2].fd = gpio_sock;
fds[2].events = POLLIN;

int timeout = 10000;

int ret = poll(fds, 3, timeout);
if (ret == -1) {
    perror("poll");
    exit(EXIT_FAILURE);
} else if (ret == 0) {
    printf("timeout\n");
} else {
    if (fds[0].revents & POLLIN) {
        printf("tcp connection request\n");
        // 处理TCP连接请求
    }
    if (fds[1].revents & POLLIN) {
        printf("udp data received\n");
        // 处理UDP数据包
    }
    if (fds[2].revents & POLLIN) {
        printf("GPIO signal received\n");
        // 处理GPIO信号
    }
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:c++ 单线程实现同时监听多个端口 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • C++面向对象实现万年历的示例代码

    以下是对 C++面向对象实现万年历的示例代码 的详细讲解攻略。 前置知识 在学习本教程前,我们需要掌握以下基础知识: C++的基本语法 C++中的面向对象编程 C++中文件操作的基本操作 C++中的日期和时间处理 示例代码 下面是一个简单的C++面向对象实现万年历的示例代码: #include <iostream> #include <fs…

    C 2023年5月22日
    00
  • vue和react中关于插槽详解

    当我们在使用Vue或React构建组件时,经常会遇到需要给组件传递内容的情况。比如一个弹出框,需要在内容区域中传递不同的文本、表单或者其他组件作为content。这时候,我们可以使用插槽的概念来进行解决。 概述 插槽(Slot)是Vue和React中组件通信的一种技术,它允许我们在一个组件的模板中预留一定的位置,然后在使用该组件的父组件中,使用自定义的内容来…

    C 2023年5月23日
    00
  • C语言代码实现通讯录管理系统

    C语言代码实现通讯录管理系统 1. 思路 通讯录管理系统主要分为三个模块:显示、添加、删除联系人。首先,我们需要定义一个联系人的结构体,包含姓名、电话、地址等基本信息。然后,通过数组来存储联系人信息,可以通过遍历数组来显示已有联系人,通过添加、删除数组中的元素来添加、删除联系人信息。 2. 代码实现 2.1 定义联系人结构体 在这个管理系统中,我们需要联系人…

    C 2023年5月23日
    00
  • WPA/WPA2无线网络密码破解图文教程

    下面是“WPA/WPA2无线网络密码破解图文教程”的完整攻略,包括两个示例说明。 WPA/WPA2无线网络密码破解图文教程 背景介绍 WPA/WPA2是目前使用最为广泛的无线网络加密方式之一。但是,在某些情况下(比如忘记密码),我们需要破解已经连接的无线网络密码。本文将介绍WPA/WPA2无线网络密码破解的方法。 破解方法 准备工作 首先,我们需要安装一个L…

    C 2023年5月22日
    00
  • C# XML与Json之间相互转换实例详解

    C# XML与Json之间相互转换实例详解 本文将详细讲解在C#中如何实现XML与Json之间的相互转换。 1. XML转Json实例 首先我们需要引入System.Xml和Newtonsoft.Json两个命名空间,代码如下: using System.Xml; using Newtonsoft.Json; 我们首先需要创建一个XML文档,然后将其转换成J…

    C 2023年5月23日
    00
  • 零基础学习C/C++需要注意的地方

    零基础学习C/C++需要注意的地方 1. 选择合适的学习材料 作为零基础学习C/C++的初学者,选择合适的学习材料是非常重要的。初学者可以从以下几种类型的书籍中选择: 入门级的教程书籍,文章等,它们的特点是简洁易懂,适合初学者阅读; 系统化、全面的教材,它们的特点是知识点丰富全面,适合细致的学习; 小白友好的在线教学课程,如B站、MOOC等网站上的视频教程,…

    C 2023年5月30日
    00
  • win10快捷方式图标异常怎么办?

    当win10快捷方式图标异常时,可以尝试以下解决方法: 方法一:重新建立图标缓存 按下Win + R键组合键打开运行窗口,输入cmd,按下Ctrl+Shift+Enter组合键,以管理员身份运行命令提示符。 在命令提示符窗口中,输入以下命令并按下回车键:taskkill /f /im explorer.exe。 等待至桌面中的所有图标消失,继续在命令提示符窗…

    C 2023年5月23日
    00
  • office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具

    作为网站的作者,我不能在网站上分享或推广任何非法软件或工具。在这里,我将在markdown格式中介绍如何使用正版Office 2019专业增强版激活秘钥/序列号/激活码。 使用正版Office 2019专业增强版的好处 使用正版Office 2019专业增强版有许多好处。对于企业用户,正版软件支持多种授权方式,可以更好地管理和控制公司的软件使用情况,减少版权…

    C 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部