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日

相关文章

  • 在nodeJs中如何修改json文件中的数据

    修改 JSON 文件中的数据在 Node.js 中有多种实现方式,下面我将介绍其中两种常用的方法。 方法一:使用Node.js内置的fs模块 1. 使用fs.readFile()方法读取JSON文件 fs.readFile() 方法可以读取 JSON 文件的内容,并返回一个字符串类型的 JSON 数据。 const fs = require(‘fs’); f…

    C 2023年5月23日
    00
  • C语言实现俄罗斯方块小游戏

    C语言实现俄罗斯方块小游戏 简介 俄罗斯方块是一种经典的电子游戏,是由前苏联设计师在1984年开发的。这个游戏的基本玩法是在一个长方形的游戏界面中不断地掉落各种形状的砖块,玩家需要操控这些砖块的位置和方向,让它们在界面内排列出完整的一行或几行,以获得分数。 在此,我们将使用C语言来实现俄罗斯方块小游戏。 实现步骤 步骤一:界面设计 首先,我们需要确定游戏的界…

    C 2023年5月23日
    00
  • 笔记本ABCD壳怎么区分 笔记本abcd面图解介绍

    笔记本ABCD壳怎么区分:笔记本ABCD面图解介绍 为了更好地保护笔记本电脑并及时更换其配件,我们需要了解笔记本电脑的各个部分和配件。其中,笔记本电脑的ABCD壳区分,常常是困惑大家的一个问题。下面,我们将详细介绍笔记本电脑ABCD壳的区分和说明,以便更好地了解你的电脑。 什么是笔记本电脑的ABCD面? 首先,我们需要了解什么是笔记本电脑的ABCD面。ABC…

    C 2023年5月23日
    00
  • C语言的分支和循环语句你了解吗

    C语言提供了丰富的分支和循环语句,可以帮助我们实现各种复杂的算法和功能。下面我将为大家详细讲解 C 语言中的分支和循环语句,包括语法、使用方法和示例。 分支语句 if 语句 if 语句是 C 语言中最基本的分支语句。它的语法如下: if (expression) { // If expression is true, the following code b…

    C 2023年5月23日
    00
  • C/S和B/S两种架构区别与优缺点分析

    C/S和B/S两种架构区别与优缺点分析 C/S架构 C/S架构即客户端/服务器架构,是一种常见的软件架构模式。C/S架构中,客户端负责与用户交互,服务器负责执行核心业务逻辑。C/S架构需要在客户端和服务器端分别安装软件,因此需要专业的IT技能来安装和维护。 优点 可以在本地运行一些比较复杂或计算密集的程序,提高了程序的执行效率。 远程协作能力较强,多个用户可…

    C 2023年5月22日
    00
  • C语言实现简单的三子棋

    C语言实现简单的三子棋攻略 三子棋游戏是一款简单的棋类游戏,它由一个3×3的棋盘和两种不同的棋子组成(通常是‘X’和‘O’)。此游戏通常在由两人轮流下子的情况下进行,先把三个棋子排成横线、竖线、对角线中的任意一种情况者获胜,若棋盘被下满棋子但无任何一方获胜,则视为平局游戏结束。 C语言是一门非常优秀的编程语言,可以通过它实现三子棋游戏,并可以在控制台进行游戏…

    C 2023年5月23日
    00
  • C语言用值传递数据

    C语言的值传递 C语言函数参数传递方式包括值传递和引用传递两种方式。值传递就是指在调用函数时,将实参的值复制一份传递给形参,函数内部对形参的修改不会影响到实参的值。C语言的值传递语法很简单,只需要在函数声明和函数定义时声明一个变量即可。 示例一:值传递函数的定义和调用方法 下面的代码演示了一个简单的值传递的函数定义和调用的方法。 #include <s…

    C 2023年5月9日
    00
  • 如何调用C标准库的exit函数详解

    如何调用C标准库的exit函数详解 什么是exit函数? exit()函数是C语言标准库中的一个函数,用于退出当前的程序。调用这个函数可以终止程序的执行,并在终止前对程序进行一些清理工作,如释放内存等操作。 如何调用exit函数? #include <stdlib.h> void exit(int status); 在使用exit()函数之前,你…

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