libevent实现UDP通信

2023-11-02

因为libevent在底层上是没有直接支持udp通信,并且在Windows上,对于udp的iocp操作,libevent也不支持(实际Windows本身是支持IOCP实现UDP通信的)

不过仍然可以利用libevent实现udp通信,调试源码发现,libevent是通过select模型去实现的。

下面的例子实现了先绑定某个端口,当收到消息时,udpread_cb发生回调。

如果不需要绑定端口,那么就需要先sendto后,才能够收到消息,udpread_cb才会发生回调。

同样的,如果需要在多个线程中进行操作,那么可以创建多个event_base

#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>

#ifdef _WIN32
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "event.lib")
#pragma comment(lib, "event_extra.lib")
#pragma comment(lib, "event_core.lib")
#else
#include <netinet/in.h>
#include <pthread.h>
# ifdef _XOPEN_SOURCE_EXTENDED
#  include <arpa/inet.h>
# endif
#include <sys/socket.h>
#define GetCurrentThreadId() pthread_self()
#endif

#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/util.h>
#include <event2/event.h>
#include <event2/thread.h>

static const char MESSAGE[] = "Hello, World!\n";

static const int PORT = 9638;

static struct event_base * createEventBase();
static evutil_socket_t createUdp(unsigned short port);
static void udpread_cb(evutil_socket_t, short, void *);

typedef struct tagUdpCtx {
    evutil_socket_t fd;
    struct event* ev;
}UdpCtx;

int mainUdp(int argc, char **argv)
{
    struct event_base *base;

#ifdef WIN32
    WSADATA wsa_data;
    WSAStartup(0x0202, &wsa_data);
#endif

    base = createEventBase();

    if (!base)
    {
        fprintf(stderr, "Could not initialize libevent!\n");
        return 1;
    }

    int iCnt;
    scanf("%d", &iCnt);
    UdpCtx* pCtx = new UdpCtx[iCnt];
    for (int i = 0; i < iCnt; ++i)
    {
        memset(&(pCtx[i]), 0, sizeof(pCtx[i]));
        pCtx[i].fd = createUdp(64000 + i);
        pCtx[i].ev = event_new(base, pCtx[i].fd, EV_READ | EV_PERSIST, udpread_cb, NULL);
        event_add(pCtx[i].ev, NULL);
    }

    printf("main GetCurrentThreadId()=%d\n", GetCurrentThreadId());
    event_base_dispatch(base); //这里面进入循环了

    for (int i = 0; i < iCnt; ++i)
    {
        evutil_closesocket(pCtx[i].fd);
        if (pCtx[i].ev)event_free(pCtx[i].ev);
    }
    delete[] pCtx;
    event_base_free(base);

#ifdef WIN32
    WSACleanup();
#endif
    printf("done\n");
    return 0;
}

static struct event_base * createEventBase()
{
    struct event_base *base = NULL;

    base = event_base_new();

    return base;
}

evutil_socket_t createUdp(unsigned short port)
{
    struct sockaddr_in sin;
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(port);
    sin.sin_addr.s_addr = INADDR_ANY;
    //evutil_inet_pton(sin.sin_family, "192.168.1.100", (void*)&sin.sin_addr);

    evutil_socket_t fd = socket(AF_INET, SOCK_DGRAM, 0);
    
    if(::bind(fd, (struct sockaddr *) &sin, sizeof(sin))!=0)
    {
        printf("bind error:%s,%d\n", evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()), EVUTIL_SOCKET_ERROR());
        evutil_closesocket(fd);
        return EVUTIL_INVALID_SOCKET;
    }

    return fd;
}

static void udpread_cb(evutil_socket_t fd, short ev, void *)
{
    printf("udpread_cb GetCurrentThreadId()=%d\n", GetCurrentThreadId());
    //evutil_closesocket(fd);
    
    char buff[1024] = "";
    struct sockaddr_in addr;
    int iLen = sizeof(addr);
    memset(&addr, 0, iLen);

    int iRet = recvfrom(fd, buff, 1023, 0, (struct sockaddr*)&addr, &iLen);
    if (iRet >= 0)
    {
        char szIp[100] = "";
        unsigned short iPort = ntohs(addr.sin_port);
        evutil_inet_ntop(addr.sin_family, (void*)&addr.sin_addr, szIp, 100);
        printf("recv(%s:%hu):%s\n",szIp, iPort, buff);

        const char* psz = "hello";
        sendto(fd, psz, strlen(psz), 0, (struct sockaddr*)&addr, iLen);
    }
    else
    {
        printf("udpread_cb error:%s,%d\n", evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()), EVUTIL_SOCKET_ERROR());
        evutil_closesocket(fd);
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

libevent实现UDP通信 的相关文章

  • 在搜索 List 时,为什么 Enumerable.Any(Func predicate) 比带有 if 语句的 foreach 慢

    最近有件事引起了我的好奇心 Why is the Enumerable Any Func
  • 以编程方式检查页面是否需要基于 web.config 设置进行身份验证

    我想知道是否有一种方法可以检查页面是否需要基于 web config 设置进行身份验证 基本上如果有这样的节点
  • 为什么大多数 C 开发人员使用 Define 而不是 const? [复制]

    这个问题在这里已经有答案了 在许多程序中 define与常量具有相同的用途 例如 define FIELD WIDTH 10 const int fieldWidth 10 我通常认为第一种形式优于另一种形式 它依赖于预处理器来处理基本上是
  • 如何创建可以像 UserControl 一样编辑的 TabPage 子类?

    我想创建一个包含一些控件的 TabPage 子类 并且我想通过设计器来控制这些控件的布局和属性 但是 如果我在设计器中打开子类 我将无法像在 UserControl 上那样定位它们 我不想创建一个带有 UserControl 实例的 Tab
  • 使用post方法将多个参数发送到asp.net core 3 mvc操作

    使用 http post 方法向 asp net mvc core 3 操作发送具有多个参数的 ajax 请求时存在问题 参数不绑定 在 dot net 框架 asp net web api 中存在类似的限制 但在 asp net mvc
  • C++:重写已弃用的虚拟方法时出现弃用警告

    我有一个纯虚拟类 它有一个纯虚拟方法 应该是const 但不幸的是不是 该接口位于库中 并且该类由单独项目中的其他几个类继承 我正在尝试使用这个方法const不会破坏兼容性 至少在一段时间内 但我找不到在非常量方法重载时产生警告的方法 以下
  • 构造函数中显式关键字的使用

    我试图了解 C 中显式关键字的用法 并查看了这个问题C 中的explicit关键字是什么意思 https stackoverflow com questions 121162 但是 那里列出的示例 实际上是前两个答案 对于用法并不是很清楚
  • C++ 异步线程同时运行

    我是 C 11 中线程的新手 我有两个线程 我想让它们同时启动 我可以想到两种方法 如下 然而 似乎它们都没有按照我的预期工作 他们在启动另一个线程之前启动一个线程 任何提示将不胜感激 另一个问题是我正在研究线程队列 所以我会有两个消费者和
  • 暂停下载线程

    我正在用 C 编写一个非常简单的批量下载程序 该程序读取要下载的 URL 的 txt 文件 我已经设置了一个全局线程和委托来更新 GUI 按下 开始 按钮即可创建并启动该线程 我想要做的是有一个 暂停 按钮 使我能够暂停下载 直到点击 恢复
  • C 语言中 =+(等于加)是什么意思?

    我碰到 与标准相反 今天在一些 C 代码中 我不太确定这里发生了什么 我在文档中也找不到它 In ancientC 版本 相当于 它的残余物与最早的恐龙骨头一起被发现 例如 B 引入了广义赋值运算符 使用x y to add y to x
  • 如何重置捕获像素的值

    我正在尝试创建一个 C 函数 该函数返回屏幕截图位图中每四个像素的 R G 和 B 值 这是我的代码的一部分 for int ix 4 ix lt 1366 ix ix 4 x x 4 for int iy 3 iy lt 768 iy i
  • 生产代码中的 LRU 实现

    我有一些 C 代码 需要使用 LRU 技术实现缓存替换 目前我知道两种实现LRU缓存替换的方法 每次访问缓存数据时使用时间戳 最后比较替换时的时间戳 使用缓存项的堆栈 如果最近访问过它们 则将它们移动到顶部 因此最后底部将包含 LRU 候选
  • 为什么我不应该对不是由 malloc() 分配的变量调用 free() ?

    我在某处读到 使用它是灾难性的free删除不是通过调用创建的对象malloc 这是真的 为什么 这是未定义的行为 永远不要尝试它 让我们看看当您尝试时会发生什么free 自动变量 堆管理器必须推断出如何获取内存块的所有权 为此 它要么必须使
  • 获取 2 个数据集 c# 中的差异

    我正在编写一个简短的算法 它必须比较两个数据集 以便可以进一步处理两者之间的差异 我尝试通过合并这两个数据集并将结果更改放入新的数据集来实现此目标 我的方法如下所示 private DataSet ComputateDiff DataSet
  • 耐用功能是否适合大量活动?

    我有一个场景 需要计算 500k 活动 都是小算盘 由于限制 我只能同时计算 30 个 想象一下下面的简单示例 FunctionName Crawl public static async Task
  • 结构体指针的动态数组

    我必须使用以下代码块来完成学校作业 严格不进行任何修改 typedef struct char firstName char lastName int id float mark pStudentRecord pStudentRecord
  • 什么是 __declspec 以及何时需要使用它?

    我见过这样的例子 declspec在我正在阅读的代码中 它是什么 我什么时候需要使用这个构造 这是 Microsoft 对 C 语言的特定扩展 它允许您使用存储类信息来赋予类型或函数属性 文档 declspec C https learn
  • 转到定义:“无法导航到插入符号下的符号。”

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 我今天突然开始在我的项目中遇到一个问题 单击 转到定义 会出现一个奇怪的错误 无法导航到
  • 我在在线程序挑战编译器中遇到演示错误

    include
  • 是否可以在 C# 中强制接口实现为虚拟?

    我今天遇到了一个问题 试图重写尚未声明为虚拟的接口方法的实现 在这种情况下 我无法更改接口或基本实现 而必须尝试其他方法 但我想知道是否有一种方法可以强制类使用虚拟方法实现接口 Example interface IBuilder

随机推荐

  • 兼容火狐--常见问题修改

    此文为本人在实际工作中遇到的情况做的记录 所以比较乱 主要用于自己日后查看 如果对大家有帮助 当然也更好 最普遍的情况 当遇到功能不好使的情况 首先按f12看控制台有没有报错 A如果有定位错误 常见错误 window frames ifra
  • Qt与MSVC中文乱码问题的解决方案

    一 问题是什么 在学习Qt编程的过程中 大多数人都遇到过中文乱码的问题 总结起来有三类 1 Qt Creator中显示的汉字变为乱码 编辑器上方有 Could not decode with UTF 8 encoding Editing n
  • PHP与MySQL程序设计 学习笔记 第二章 环境配置

    主流Linux发行包中都加入了Apache 如果没有 也可以利用发行包的打包服务轻松安装 如Ubuntu的apt get命令 http httpd apache org download cgi可导航到离你最近的镜像站点 windows安装
  • 如何查看linux服务器的版本和配置信息

    linux下看配置 可没有windows那么直观 你只能一个一个查看 一 cpu root srv more proc cpuinfo grep modelname root srv grep model name proc cpuinfo
  • python quit()讲解_Python:pygame.QUIT()

    Just been messing around with pygame and ran into this error CODE import sys import pygame pygame init size width height
  • pytorch入门级教程——分类代码分析与实现(iris数据集)

    用iris数据进行分类训练 并可视化 首先导入API import torch import torch nn functional as F import matplotlib pyplot as plt from sklearn dec
  • 斐波那契数列的对数时间复杂度计算分析(说服你对数时间复杂度是可以算的)+求平方的对数时间分析

    我先强调一下 请侧重注意时间复杂度 不要在意语句的作用 先上一下斐波那契的代码 解释在注释里面 跟语言没关系 都差不多啦 大家想看别的语言的解释 没学过Java也能看 只是它在第一个 我就直接复制了 真的 力扣 先上只看时间复杂度的句子 c
  • 离散数学和算法

    特点 离散数学涉及研究可数的 不同的元素 其原理广泛用于构建计算机科学和数据科学的算法 离散数学概念的知识将帮助您理解位于数据驱动任务核心的算法 二进制和通用数学 快速掌握离散数学原理 在学习离散数学语言时 还将学习对研究和描述计算机科学和
  • 【浅谈算法】1-冒泡排序优化(JAVA实现)

    原理 从左至右遍历数组 每两个数比较一次 并将大数向右移 如 给定数组 5 1 9 7 实现从左至右依次由小到大的排序 其步骤为 第一趟操作 1 比较 5 1 两个数 如果左数大于右数 则将两数交换位置 反之则不变 因为5 gt 1 所以交
  • 基于SSM+MySQL+Layui的客户关系信息管理系统

    登陆 登陆首页 市场活动 活动详情 线索管理 线索详情 客户管理 联系人 交易管理 交易管理 个人信息 角色信息 技术描述 开发工具 Idea Eclipse 数据库 mysql Jar包仓库 Maven 前段框架 jquery Jsp 后
  • 【python与数据分析】实验十三 北京市空气质量

    目录 一 实验内容 二 完成情况 三 数据分析 1 问题描述 2 编程思路 3 程序代码 4 程序运行结果 1 2014年 2019年AQI时间序列折线图 2 各年AQI折线图 AQI直方图 PM2 5与AQI散点图 空气质量整体情况的饼图
  • Linux Git-v2.35.1的安装与配置

    Git v2 35 1的安装与配置 Git官网下载地址 1 下载安装包和依赖库 解压 检查 编译 安装 删除安装包和解压目录 wget https mirrors edge kernel org pub software scm git g
  • WGS84坐标转火星坐标(iOS篇)

    WGS84坐标转火星坐标 iOS篇 转自 keakon的涂鸦馆 http www keakon net 2011 07 02 WGS84 E5 9D 90 E6 A0 87 E8 BD AC E7 81 AB E6 98 9F E5 在这个
  • 需求分析和系统分析的区别

    需求分析 透过调研问卷 访谈等方式 挖掘客户所描述需求背后的管理诉求和要解决的问题 需求分析 不是简单的重述客户的描述 其实就是 问诊 1 客户说谈是否仅仅只是现象 2 客户所谈这种现象 是在什么条件下 基于什么背景产生的 3 这种现象 对
  • 毕业设计-基于违禁品的检测深度卷积网络- YOLO

    目录 前言 课题背景和意义 实现技术思路 一 网络 二 模型的改进 实现效果图样例 最后 前言 大四是整个大学期间最忙碌的时光 一边要忙着备考或实习为毕业后面临的就业升学做准备 一边要为毕业设计耗费大量精力 近几年各个学校要求的毕设项目越来
  • 可靠传输的基本概念

    可靠传输的基本概念 使用差错检错技术 接受方的数据链路层就可以检测出真在传输过程中是否出现误码 这取决于数据链路层向上层提供的服务类型 不可靠传输 仅仅丢弃有误码的帧 其他的什么也不做 可靠传输 想方法实现发送端发送什么 接收端就收到什么
  • 我与老式硬盘的相爱相杀(1)

    瞎废话 本人是一位初一男生 最近在和朋友研究移动硬盘 这篇内容是我的第一篇原创 请大家多多支持 事情起因 原来 我们两个几乎啥都不懂的人打算解析一下主机结构 可是网上的那些图片大多都不够直观 没有那种立体感 刚好 我家里有一台我爸爸很久以前
  • linux判断两个文件内容,shell怎么判断两个文件内容是否相同

    cat diff two file bin sbin file1 mnt mmc test aa file2 mnt mmc test bb diff file1 file2 gt dev null if 0 0 then echo Bot
  • Base64在线解析,编码转化为图片

    博主介绍 22届计科专业毕业 来自湖南 主要是在CSDN记录一些自己在Java开发过程中遇到的一些问题 欢迎大家一起讨论学习 也欢迎大家的批评指正 前言 虽然我自己Base64在线解析用的少 但是避免不了需要使用的时候 这次我需要将Base
  • libevent实现UDP通信

    因为libevent在底层上是没有直接支持udp通信 并且在Windows上 对于udp的iocp操作 libevent也不支持 实际Windows本身是支持IOCP实现UDP通信的 不过仍然可以利用libevent实现udp通信 调试源码