Libevent UDP开发指南
UDP 与 TCP 的核心区别
-
无连接:不需要建立/维护连接
-
不可靠:不保证数据包顺序和到达
-
高效:头部开销小,没有连接管理负担
-
支持广播/多播:可以向多个目标同时发送数据
一、基础UDP服务器实现
1. 创建 UDP 套接字
#include <event2/event.h>
#include <event2/listener.h>
#include <event2/bufferevent.h>
#include <arpa/inet.h>int create_udp_socket(int port) {int fd = socket(AF_INET, SOCK_DGRAM, 0);if (fd < 0) {perror("socket");return -1;}struct sockaddr_in sin;memset(&sin, 0, sizeof(sin));sin.sin_family = AF_INET;sin.sin_port = htons(port);sin.sin_addr.s_addr = htonl(INADDR_ANY);if (bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) {perror("bind");close(fd);return -1;}// 设置非阻塞evutil_make_socket_nonblocking(fd);return fd;
}
2. UDP 事件处理
void udp_read_cb(evutil_socket_t fd, short events, void *arg) {struct sockaddr_in client_addr;socklen_t addr_len = sizeof(client_addr);char buf[1500]; // 标准MTU大小ssize_t n;while ((n = recvfrom(fd, buf, sizeof(buf), 0,(struct sockaddr*)&client_addr, &addr_len)) > 0) {// 处理接收到的数据printf("Received %zd bytes from %s:%d\n", n, inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));// 简单回显sendto(fd, buf, n, 0, (struct sockaddr*)&client_addr, addr_len);}if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {perror("recvfrom");}
}int main() {int udp_fd = create_udp_socket(8080);if (udp_fd < 0) return 1;struct event_base *base = event_base_new();struct event *udp_event = event_new(base, udp_fd, EV_READ | EV_PERSIST, udp_read_cb, NULL);event_add(udp_event, NULL);printf("UDP server started on port 8080\n");event_base_dispatch(base);event_free(udp_event);close(udp_fd);event_base_free(base);return 0;
}
3. UDP 服务器示例代码
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <time.h>#define MAX_CLIENTS 10000
#define MAX_PACKET_SIZE 1500struct udp_client {struct sockaddr_in addr;time_t last_active;
};struct udp_server {struct event_base *base;int sockfd;struct event *ev;struct udp_client clients[MAX_CLIENTS];
};void udp_read_cb(evutil_socket_t fd, short events, void *arg) {struct udp_server *server = arg;char buf[MAX_PACKET_SIZE];struct sockaddr_in client_addr;socklen_t addr_len = sizeof(client_addr);ssize_t n = recvfrom(fd, buf, sizeof(buf), 0,(struct sockaddr*)&client_addr, &addr_len);if (n <= 0) return;// 查找或创建客户端记录struct udp_client *client = NULL;for (int i = 0; i < MAX_CLIENTS; i++) {if (memcmp(&server->clients[i].addr, &client_addr, addr_len) == 0) {client = &server->clients[i];break;}}if (!client) {// 查找空闲槽位for (int i = 0; i < MAX_CLIENTS; i++) {if (server->clients[i].last_active == 0) {client = &server->clients[i];memcpy(&client->addr, &client_addr, addr_len);break;}}}if (client) {client->last_active = time(NULL);// 业务处理printf("Received %zd bytes from %s:%d\n", n, inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));// 回显sendto(fd, buf, n, 0, (struct sockaddr*)&client_addr, addr_len);} else {printf("Client limit reached, dropping packet\n");}
}struct udp_server* udp_server_create(int port) {struct udp_server *server = malloc(sizeof(struct udp_server));memset(server, 0, sizeof(*server));// 创建socketserver->sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (server->sockfd < 0) {perror("socket");free(server);return NULL;}// 绑定地址struct sockaddr_in sin;memset(&sin, 0, sizeof(sin));sin.sin_family = AF_INET;sin.sin_port = htons(port);sin.sin_addr.s_addr = htonl(INADDR_ANY);if (bind(server->sockfd, (struct sockaddr*)&sin, sizeof(sin)) < 0) {perror("bind");close(server->sockfd);free(server);return NULL;}// 设置非阻塞evutil_make_socket_nonblocking(server->sockfd);// 创建事件基server->base = event_base_new();if (!server->base) {close(server->sockfd);free(server);return NULL;}// 创建事件server->ev = event_new(server->base, server->sockfd, EV_READ | EV_PERSIST, udp_read_cb, server);event_add(server->ev, NULL);return server;
}void udp_server_run(struct udp_server *server) {event_base_dispatch(server->base);
}void udp_server_free(struct udp_server *server) {if (!server) return;if (server->ev) event_free(server->ev);if (server->base) event_base_free(server->base);if (server->sockfd > 0) close(server->sockfd);free(server);
}int main() {struct udp_server *server = udp_server_create(8080);if (!server) return 1;printf("UDP server started on port 8080\n");udp_server_run(server);udp_server_free(server);return 0;
}
4. UDP 客户器示例代码
#include <event2/event.h>
#include <event2/dns.h>
#include <event2/bufferevent.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>struct udp_client {struct event_base *base;struct evdns_base *dns;int sockfd;struct sockaddr_in server_addr;int connected;pthread_mutex_t lock;
};void udp_read_cb(evutil_socket_t fd, short events, void *arg) {struct udp_client *client = arg;char buf[1500];struct sockaddr_in from_addr;socklen_t addr_len = sizeof(from_addr);ssize_t n = recvfrom(fd, buf, sizeof(buf), 0,(struct sockaddr*)&from_addr, &addr_len);if (n > 0) {buf[n] = '\0';pthread_mutex_lock(&clie相关文章:
Libevent UDP开发指南
UDP 与 TCP 的核心区别 无连接:不需要建立/维护连接 不可靠:不保证数据包顺序和到达 高效:头部开销小,没有连接管理负担 支持广播/多播:可以向多个目标同时发送数据 一、基础UDP服务器实现 1. 创建 UDP 套接字 #include <event2/event.h> #include <event2/lis…...
Android View事件分发机制深度解析
在Android面试中,关于View事件分发机制的考察往往不仅限于基础流程,更关注底层原理、性能优化和实际应用场景。以下是针对面试的全面回答策略: 一、基础回答框架 核心三要素: 传递流程 "事件分发遵循Activity → Window →…...
如何在 GitHub 上开源一个小项目:从创建到长期维护的完整指南
如何在 GitHub 上开源一个小项目:从创建到长期维护的完整指南 适用于 个人开发者、团队合作、企业开源,涵盖 Git 基础、GitHub 配置、最佳实践、社区互动、自动化 CI/CD 及长期维护策略。 📌 1. 注册 GitHub 账户 如果你还没有 GitHub 账户&…...
autoconf 笔记250404
autoconf autoconf 是 Linux 系统中控制 IPv6 无状态地址自动配置(SLAAC) 的关键参数,位于 /proc/sys/net/ipv6/conf/<接口>/ 目录下。它决定接口是否根据接收到的 路由通告(Router Advertisement, RA) 自动生成…...
5天速成ai agent智能体camel-ai之第1天:camel-ai安装和智能体交流消息讲解(附源码,零基础可学习运行)
嗨,朋友们!👋 是不是感觉AI浪潮铺天盖地,身边的人都在谈论AI Agent、大模型,而你看着那些密密麻麻的代码,感觉像在读天书?🤯 别焦虑!你不是一个人。很多人都想抓住AI的风…...
FPGA——FPGA状态机实现流水灯
一、引言 在FPGA开发中,状态机是一种重要的设计工具,用于处理具有时间顺序的事件。本文将详细介绍如何使用状态机实现一个LED流水灯的效果。 二、状态机概述 状态机(FSM)是一种行为模型,用于表示系统在不同状态下的…...
晶晨S905-S905L-S905LB_S905M2通刷_安卓6.0.1_16S极速开机_线刷固件包
晶晨S905-S905L-S905LB_S905M2通刷_安卓6.0.1_16S极速开机_线刷固件包 线刷方法:(新手参考借鉴一下) 刷机工具版本请用2.2.0以上,导入固件后,刷机工具右侧两个擦除打勾,然后点开始。插上刷机神器…...
构建第一个ArkTS应用:Hello World之旅
# 构建第一个ArkTS应用:Hello World之旅 在鸿蒙应用开发的领域中,ArkTS语言为我们提供了强大而便捷的开发方式。今天,就让我们一起踏上构建第一个ArkTS应用——Hello World的奇妙旅程。 ## 一、创建ArkTS工程 1. 首先,我们要使用…...
第十五届单片机模拟考试III
题目 题目不长 ,功能也不难,一道水题 按键功能 S4界面切换,S5 功能切换,在不同界面转换不同的功能,定义两个标志位记录即可。 S9复位,回到初始状态,记得界面也得回到初始的信号界面࿰…...
测试:正交法设计测试用例
目录 一、什么是正交法 二、利用正交表设计测试用例 正交法设计测试用例的步骤 一、什么是正交法 正交法的目的是为了减少测试用例的数量,让尽可能少的用例覆盖两两组合。认识正交表。 最简单的正交表是L4(2^3),含意如下: “L”代表正…...
生成 SSH Key 并配置 GitHub/GitLab 详细教程
🔑 生成 SSH Key 并配置 GitHub/GitLab 详细教程 🟢 第 1 步:检查是否已有 SSH Key 在 Git Bash (Windows)、终端 (Linux/macOS) 运行以下命令: ls -al ~/.ssh🔹 可能的输出: 如果已有 SSH Key…...
[ctfshow web入门] web5
前置知识 引用博客:phps的利用 当服务器配置了 .phps 文件类型时,访问 .phps 文件会以语法高亮的形式直接显示 PHP 源代码,而不是执行它。.phps被作为辅助开发者的一种功能,开发者可以通过网站上访问xxx.phps直接获取高亮源代码 …...
Qt基本框架(2)
本篇主要介绍如何设置窗口,以及在窗口中添加按钮 本文部分ppt、视频截图原链接:[萌马工作室的个人空间-萌马工作室个人主页-哔哩哔哩视频] 1. Qt简单框架 2. 通过QMainWindow实现简单界面 QMainWindow是构建主窗口应用的核心类,通过合理设计…...
基于javaweb的SpringBoot图片管理系统图片相册系统设计与实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…...
用HTML.CSS.JavaScript实现一个贪吃蛇小游戏
目录 一、引言二、实现思路1. HTML 结构2. CSS 样式3. JavaScript 逻辑 三、代码实现四、效果展示 一、引言 贪吃蛇是一款经典的小游戏,曾经风靡一时。今天,我们将使用 HTML、CSS 和 JavaScript 来实现一个简单的贪吃蛇小游戏。通过这个项目,…...
[特殊字符] Pandas 常用操作对比:Python 运算符 vs Pandas 函数
在 Pandas 中,许多操作可以直接使用 Python 的比较运算符(如 、!、>、< 等),而不需要调用 Pandas 的专门函数(如 eq()、ne()、gt() 等)。这些运算符在 Pandas 中已经被重载,代码更简洁。以…...
Java 实现插入排序:[通俗易懂的排序算法系列之三]
引言 大家好!欢迎继续关注我的排序算法系列。今天,我们要学习的是另一种非常基础且重要的排序算法——插入排序 (Insertion Sort)。 插入排序的思路非常贴近我们日常整理扑克牌的方式,理解起来相对自然。虽然它在最坏情况下的效率不高,但在某些特定场景下,它的表现甚至优…...
使用MATIO库写入MATLAB结构体(struct)数据的示例程序
使用MATIO库写入MATLAB结构体(struct)数据的示例程序 MATIO是一个用于读写MATLAB数据文件(.mat)的开源C库。下面是一个完整的示例程序,展示如何使用MATIO库创建一个包含结构体数据的MAT文件。 示例程序 #include <stdio.h> #include <stdlib.h> #inc…...
JVM——模型分析、回收机制
方法区:存储已被虚拟机加载的类元数据信息(元空间) 堆:存放对象实例,几乎所有的对象实例都在这里分配内存 虚拟机栈:虚拟机栈描述的是|ava方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局…...
7. 记忆(Memory)机制:让AI拥有“短期记忆”与“长期记忆”
引言:当AI学会"记住你" 2025年某银行智能客服因无法记住用户身份,每次对话都要求重复验证,引发大量投诉。引入LangChain 记忆系统后,客户满意度提升62%。本文将基于MemorySaver与FAISS本地存储,教你构建符合…...
前后端分离下,Spring Boot 请求从发起到响应的完整执行流程
以下是前后端分离架构下,Spring Boot 请求从发起到响应的完整执行流程,结合你提出的所有问题,按真实执行顺序和职责链条重新整理所有核心概念、结构、关键类、数据转换点和典型代码示例: 一、前端发起请求(步骤1-2&…...
【文献阅读】Vision-Language Models for Vision Tasks: A Survey
发表于2024年2月 TPAMI 摘要 大多数视觉识别研究在深度神经网络(DNN)训练中严重依赖标注数据,并且通常为每个单一视觉识别任务训练一个DNN,这导致了一种费力且耗时的视觉识别范式。为应对这两个挑战,视觉语言模型&am…...
【BFS最小步数】魔板题解
魔板题解 题目传送门 题目传送门 一、题目描述 Rubik先生发明了魔板的二维版本,这是一个有8个格子的板子,初始状态为: 1 2 3 4 8 7 6 5我们可以用三种操作来改变魔板状态: A:交换上下两行B:将最右边一…...
搭建K8S-1.23
0、简介 这里只用3台服务器来做一个简单的集群 地址主机名192.168.160.40kuber-master-1192.168.160.41kuber-master-2192.168.160.42kuber-node-1 1、关闭三个服务 (1)防火墙 systemctl stop firewalld (2)Selinux setenf…...
AOP在SpringBoot项目中的简单使用场景
SpringBoot AOP的简单使用 添加DTO添加controller(同包不同类)控制器1控制器2 AOP场景演示1. 对某package下的所有接口进行方法执行前逻辑校验新增切面,编写处理逻辑 2. 对某controller类下的所有接口进行方法执行前逻辑校验新增切面,编写处理逻辑 3. 对…...
windows如何安装wkhtmltoimage 给PHP使用根据HTML生成图片
windows如何安装wkhtmltoimage 给PHP使用 在Windows系统上安装wkhtmltoimage以便在PHP中使用,通常涉及到以下几个步骤: 下载wkhtmltoimage 首先,你需要从wkhtmltopdf的官方网站( https://wkhtmltopdf.org/downloads.html …...
代码仓库使用git lfs上传模型文件
一 Git LFS是什么 它主要是用来处理大文件的,比如模型文件通常都很大,超过100MB的话,用普通的Git上传可能会出问题,所以必须用LFS。 二 具体步骤 Windows环境下使用Git LFS上传大模型文件到代码仓库: 2.1ÿ…...
AI比人脑更强,因为被植入思维模型【42】思维投影思维模型
giszz的理解:本质和外在。我们的行为举止,都是我们的内心的表现。从外边可以看内心,从内心可以判断外在。曾国藩有7个识人的方法,大部分的人在他的面前如同没穿衣服一样。对于我们自身的启迪,我认为有四点&…...
Git 从入门到精通(开源协作特别版)
🧠 Git 从入门到精通(开源协作特别版) ✅ 基础命令 🧰 高级用法 🛠️ 开源实战技巧 🌍 GitHub 社区协作 适合:从0开始 → 熟练开发者 → 参与/维护开源项目 🔰 第1章:…...
spring-cloud-alibaba-nacos-config使用说明
一、核心功能与定位 Spring Cloud Alibaba Nacos Config 是 Spring Cloud Alibaba 生态中的核心组件之一,专为微服务架构提供动态配置管理能力。它通过整合 Nacos 的配置中心功能,替代传统的 Spring Cloud Config,提供更高效的配置集中化管理…...
