KRTS网络模块:UDP通信

news2024/11/15 9:32:03

KRTS网络模块:UDP通信


目录

  • KRTS网络模块:UDP通信
    • UDP简介
    • KRST UDP简介
        • 核心特性
        • 界面设计
    • 核心代码
    • 运行实例
        • 稳定性测试


UDP简介

UDP(User Datagram Protocol,用户数据报协议)是一种无连接的传输层协议,它位于OSI七层模型中的传输层,并且使用IP作为底层协议来发送数据。UDP的主要特点是它提供了轻量级的数据传输服务,不保证数据的可靠性、顺序性和流量控制。这意味着使用UDP发送的数据报可能丢失、重复或乱序到达,而且发送端并不追踪这些数据报是否成功到达接收端。由于UDP不进行连接管理,因此它的开销非常小,非常适合用于实时应用,如语音通话、视频会议和在线游戏等场景,这些应用能够容忍一定程度的数据丢失,但要求低延迟和高效率的数据传输。此外,UDP还被广泛应用于多播和广播通信中。

KRST UDP简介

KRTS UDP作为一个UDP协议的一个变种,其主要功能包括支持IP地址和端口配置、实时数据处理以及能够接受来自通用UDP和特定UDP的通信服务。KRTS UDP通过减少延迟和提高数据传输效率,确保了更流畅的实时通信体验。下面是KRTS服务端的一些核心特性和实现细节:

核心特性
  1. IP 和端口配置:
    • 支持指定服务端监听的IP地址和端口号。
    • 支持绑定到特定的网络接口。
  2. 实时数据处理:
    • 实现高效的数据处理逻辑,确保低延迟和高吞吐量。
界面设计

Qt开发应用层界面

在这里插入图片描述
在这里插入图片描述

核心代码

内核层代码

/*
 *     KRTS 网络服务器 - 内核程序
 *     时间: 2024-8-10
 *     版本: 0.1
 *     代码规范: Google 开源项目风格
 *     版权所有: 山东易码智能科技股份有限公司
 */

#include "Base/SharedData.h"

SharedData *kernel_data_ {nullptr};
KSSocketAddr remote_addr_;                       // 远程地址

/* 套接字回调函数 */
KSError __stdcall SocketCallBack(void * /*pArgs*/, void *context);

extern "C" KSError __declspec(dllexport) __stdcall InitKernel(void *args, void * /*pContext*/)
{
    KS_printK("-------------- InitKernel \n");
    kernel_data_ = static_cast<SharedData *>(args);

    /* 为传入数据创建管道。这将是一个消息管道 */
    KSError error = KS_createPipe(&kernel_data_->pipe_handle, "NetworkUdpServerPipe", 1, BUFFER_SIZE * 4, KS_INVALID_HANDLE, KSF_MESSAGE_PIPE);
    if (error != KS_OK) { return error; }

    /* 创建接收事件。 */
    error = KS_createEvent(&kernel_data_->receive_event_handle, "UdpServerReceiveEvent", KSF_NO_FLAGS);
    if (error != KS_OK) { return error; }

    // 为了对套接字上的事件做出反应,我们使用带有 KSF_DIRECT_EXEC 的回调。
    error = KS_createCallBack(&kernel_data_->socket_call_back, SocketCallBack, nullptr, KSF_DIRECT_EXEC, 0);
    if (error != KS_OK) { return error; }

    /* 打开网络适配器 */
    error = KS_openNetworkAdapter(&kernel_data_->adapter_handle, kernel_data_->device_name, nullptr, KSF_NO_FLAGS);
    if (error != KS_OK) { return error; }

    /* 网络将配置为使用在用户空间的应用程序中指定的 IP 地址、子网和网关。 */
    error = KS_execNetworkCommand(kernel_data_->adapter_handle, KS_NETWORK_SET_IP_CONFIG, &kernel_data_->ip_config, KSF_NO_FLAGS);
    if (error != KS_OK) { return error; }
    
    /* 在端口上创建一个 Udp 服务器套接字。 */
    KSSocketAddr socket_addr = {0};
    socket_addr.family = KS_FAMILY_IPV4;
    socket_addr.port = KS_htons(kernel_data_->port_config);
    *socket_addr.address = kernel_data_->ip_config.localAddress;

    error = KS_openSocket(&kernel_data_->socket_handle, kernel_data_->adapter_handle, &socket_addr, KS_PROTOCOL_UDP, KSF_NO_FLAGS);
    if (error != KS_OK){ return error;}

    // 设置套接字的最大传输单位 (MTU)。
    int mtu = 1024;
    error = KS_execSocketCommand( kernel_data_->socket_handle,  KS_SOCKET_SET_MTU, &mtu,KSF_NO_FLAGS);
    if (error != KS_OK){ return error;}

    /* 安装数据接收回调 */
    error = KS_installSocketHandler(kernel_data_->socket_handle, KS_SOCKET_RECV, kernel_data_->socket_call_back, KSF_NO_FLAGS);
    if (error != KS_OK) { return error; }

    // 初始化远程地址
    remote_addr_.family = KS_FAMILY_IPV4;
    remote_addr_.port = KS_htons(kernel_data_->port_config);
    *remote_addr_.address = kernel_data_->remote_addr;

    return KS_OK;
}

extern "C" KSError __declspec(dllexport) __stdcall ExitKernel(void * /*pArgs*/, void * /*pContext*/)
{
    KS_printK("-------------- ExitKernel \n");
    if (kernel_data_ == nullptr) { return KSERROR_FUNCTION_NOT_AVAILABLE; }
    KS_installSocketHandler(kernel_data_->socket_handle, KS_SOCKET_RECV, KS_INVALID_HANDLE, KSF_NO_FLAGS);
    /* 关闭套接字。 */
    KS_closeSocket(kernel_data_->socket_handle);
    /* 关闭网络适配器。 */
    KS_closeNetwork(kernel_data_->adapter_handle,KSF_NO_FLAGS);
    /* 移除回调。 */
    KS_removeCallBack(kernel_data_->socket_call_back);
    /*关闭事件 */
    KS_closeEvent(kernel_data_->receive_event_handle);
    /* 删除消息管道 */
    KS_removePipe(kernel_data_->pipe_handle);

    return KS_OK;
}

// 发送消息
extern "C" __declspec(dllexport) KSError __stdcall SendBufferContent(void* /*pArgs*/, void* /*pContext*/)
{
    if (kernel_data_->send_length != 0)
        {
        KSError error = KS_sendToSocket(
                    kernel_data_->socket_handle,
                    &remote_addr_,
                    kernel_data_->send_buffer,
                    kernel_data_->send_length, nullptr,
                    KSF_NO_FLAGS);

        if (error != KS_OK) {return error;}

        error = KS_sendToSocket(
                    kernel_data_->socket_handle,
                    &remote_addr_,
                    "\r\n",                            
                    2, nullptr,
                    KSF_NO_FLAGS);

        if (error != KS_OK)  { return error;}
    }

    return KS_OK;
}

// 接收消息
KSError __stdcall SocketCallBack(void * /*pArgs*/, void */* context */)
{
    KS_printK("-------------- SocketCallBack \n");

    KSError error;
    int length;

    do
    {
        byte read_buffer[BUFFER_SIZE];

        // 接收数据
        error = KS_recvFromSocket(kernel_data_->socket_handle, &remote_addr_, read_buffer, BUFFER_SIZE, &length, KSF_NO_FLAGS);
        if (error && KSERROR_CODE(error) != KSERROR_NO_DATA_AVAILABLE) { return error; }

        if (error == KS_OK)
        {
            error = KS_putPipe(kernel_data_->pipe_handle, read_buffer, length, nullptr,KSF_NO_FLAGS);

            KS_setEvent(kernel_data_->receive_event_handle);
        }
    } while (error == KS_OK);

    return KS_OK;
}

#pragma pack(push, 8)
#include <windows.h>
#pragma pack(pop)

BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD reason, LPVOID pReserved)
{
    return TRUE;
}

应用层代码

#include "KitharaUser.h"
#include "Universal/Universal.h"
#include <QtConcurrent>
#include <windows.h>

KitharaUser::KitharaUser(QObject *parent) : QObject(parent)
{
    /*  打开驱动  */
    if (const KSError error = KS_openDriver(customer_number_); error != KS_OK)
    {
        Universal::OutputErr(error, "KS_openDriver", "Unable to open the driver!");
        return;
    }
}

KitharaUser::~KitharaUser()
{
    /* 关闭驱动 */
    if (const KSError error = KS_closeDriver(); error != KS_OK)
    {
        Universal::OutputErr(error, "KS_closeDriver", "Unable to close the driver!");
    }
    Sleep(3000);
};

bool KitharaUser::Init()
{
    /* 创建共享内存 */
    KSError error = KS_createSharedMemEx(&shared_mem_handle_, "", sizeof(SharedData),KSF_NO_FLAGS);
    if (error != KS_OK)
    {
        Universal::OutputErr(error, "KS_createSharedMemEx", "Unable to create the shared memory!");
        return false;
    }

    /* 获取共享内存句柄,并于用户层数据绑定 */
    error = KS_getSharedMemEx(shared_mem_handle_, reinterpret_cast<void **>(&user_data_), KSF_NO_FLAGS);
    if (error != KS_OK)
    {
        Universal::OutputErr(error, "KS_getSharedMemEx", "Unable to get the shared memory!");
        return false;
    }

    /* 加载内核层DLl */
    error = KS_loadKernel(&user_data_->kernel_handle, "KernelUDP.dll", nullptr, nullptr,KSF_KERNEL_EXEC | KSF_SAVE_FPU);
    if (error != KS_OK)
    {
        Universal::OutputErr(error, "KS_loadKernel", "Unable to load the kernel!");
        return false;
    }

    return true;
}

bool KitharaUser::Start()
{
    /* 遍历网卡 */
    /* 获取网卡名称
     *
     * KSF_ACTIVE: 该设备不仅在Windows 系统中可用,而且还与 Kithara 驱动程序永久连接。
     *
     */
    KSError error = KS_enumDevices("NET", network_index_, user_data_->device_name, KSF_NO_FLAGS);
    if (error != KS_OK)
    {
        Universal::OutputErr(error, "KS_enumDevices", "Unable to query network device name!");
        return false;
    }

    // 为了发送 IP 数据包,我们必须设置自己的 IP 地址和子网掩码。
    // 注意:以太网帧中的数据必须是“大端”!
    KS_makeIPv4(&user_data_->ip_config.localAddress, 192, 168, 0, 182);
    KS_makeIPv4(&user_data_->ip_config.subnetMask, 255, 255, 255, 0);
    KS_makeIPv4(&user_data_->ip_config.gatewayAddress, 192, 168,   0,   1);
    KS_makeIPv4(&user_data_->remote_addr, 192, 168, 0, 161);
    user_data_->port_config = 2345;

    error = KS_execKernelFunctionEx(user_data_->kernel_handle, "InitKernel", shared_mem_handle_, KS_INVALID_HANDLE, KSF_NO_FLAGS);
    if (error != KS_OK)
    {
        Universal::OutputErr(error, "KS_execKernelFunctionEx", "Unable to initialize the kernel DLL!");
        return false;
    }

    /* 创建线程 */
    future_ = QtConcurrent::run(&KitharaUser::RecevicePipeData,this);
    return true;
}

QStringList KitharaUser::GetNetworkList() const
{
    QStringList network_list;
    for (int i = 0;; ++i)
    {
        char device_name[256];
        if (const KSError error = KS_enumDevices("NET", i, device_name, KSF_NO_FLAGS); error != KS_OK)
        {
            if (KSERROR_CODE(error) != KSERROR_DEVICE_NOT_FOUND)
            {
                Universal::OutputErr(error, "KS_enumDevices", "Unable to query network device name!");
            }
            if (KSERROR_CODE(error) == KSERROR_DEVICE_NOT_FOUND && !i)
            {
                Universal::OutputTxt("No network adapters found");
                return {};
            }

            break;
        }
        network_list.append(device_name);
    }

    return network_list;
}

void KitharaUser::SetNetworkIndex(const int index)
{
    if (index < 0)
    {
        return;
    }

    network_index_ = index;
}

void KitharaUser::WaitForStop() const
{
    while (true)
    {
        if (user_data_->is_finished == 1)
       {
            return;
        }

       if(!SendUdpData("Hello KRTS"))
       {
          Universal::OutputErr(KS_OK, "SendUdpData", "Unable to send data!");
       }
        Sleep(1000);
    }
}

void KitharaUser::Stop() const
{
    if (user_data_ != nullptr)
    {
        user_data_->is_finished = 1;
    }
}

void KitharaUser::UnInit()
{
    // 等待线程退出
    future_.waitForFinished();

    KSError error;
    /* 卸载内核层DLL */
    if (shared_mem_handle_ != NULL && user_data_->kernel_handle != NULL)
    {
        if (error = KS_execKernelFunctionEx(user_data_->kernel_handle, "ExitKernel", KS_INVALID_HANDLE, KS_INVALID_HANDLE, KSF_NO_FLAGS)
            ; error != KS_OK)
        {
            Universal::OutputErr(error, "KS_execKernelFunctionEx", "Error while deallocating resources on kernel level!");
            return;
        }

        error = KS_freeKernel(user_data_->kernel_handle);
        if (error != KS_OK)
        {
            Universal::OutputErr(error, "KS_freeKernel", "Unable to unload the kernel!");
        }
    }

    /* 释放共享内存 */
    if (shared_mem_handle_ != NULL)
    {
        error = KS_freeSharedMemEx(shared_mem_handle_, KSF_NO_FLAGS);
        if (error != KS_OK)
        {
            Universal::OutputErr(error, "KS_freeSharedMemEx", "Unable to free the shared memory!");
        }
        else
        {
            user_data_ = nullptr;
        }
    }
}

void KitharaUser::RecevicePipeData()
{
    KSError error = KS_OK;
    char read_buffer[BUFFER_SIZE];
    int length;

    while (true)
    {
        if (user_data_->is_finished != 0)
        {
            break;
        }

        error = KS_waitForEvent(user_data_->receive_event_handle, KSF_NO_FLAGS, 5 * MS);
        if (error != KS_OK) { continue; }

        while (KS_OK == KS_getPipe(user_data_->pipe_handle, read_buffer, BUFFER_SIZE, &length, KSF_NO_FLAGS))
        {
            read_buffer[length] = '\0';
            Universal::OutputTxt(read_buffer, false);
            if (auto str = QString(read_buffer); !str.isEmpty())
            {
                emit SendData(str);
            }
        }
    }

    Universal::OutputTxt("Receiving thread has been finished.");
}

bool KitharaUser::SendUdpData(const QString &message) const
{
    if (user_data_ == nullptr)
    {
        return false;
    }

    strcpy_s(user_data_->send_buffer, message.toStdString().c_str());
    user_data_->send_length = (int)message.length();
    if (const KSError error = KS_execKernelFunctionEx(user_data_->kernel_handle, "SendBufferContent", KS_INVALID_HANDLE, KS_INVALID_HANDLE, KSF_NO_FLAGS); error != KS_OK)
    {
        Universal::OutputErr(error, "SendBufferContent", "Error while sending!");
        return false;
    }

    return true;
}

运行实例

在这里插入图片描述

稳定性测试

在这里插入图片描述
根据本次测试数据,系统抖动范围在0至30.60微秒之间,其中0-1微秒区间内抖动出现频率最高,占比达23.07%。整体来看,大部分抖动集中在低值区间,表明系统具有较好的时间稳定性和可预测性。测试过程中不同硬件的测试结果会产生较大差异。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2102970.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

「对比评测」标准WPF DataGrid与DevExpress WPF GridControl有何不同?(二)

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…

NanoPC-T6安装redriod笔记

这里主要用于自己对安装过程的记录&#xff0c;中间可能记录比较粗糙。 重新编译内核 参考链接&#xff1a;【环境搭建】基于linux的NanoPC-T6_LTS系统固件编译环境搭建 基于docker构建编译环境 docker run -it \ --privilegedtrue --cap-addALL \ --name nanopc_t6_lts_en…

协同开发工具Git

网上对于Git的使用方法介绍的很多&#xff0c;在日常工作中&#xff0c;Git是团队开发必不可少的工具之一&#xff0c;我想为一些刚使用Git的小伙伴们介绍一下常遇到的小问题。 1&#xff1a;拼写错误。这应该是每个初学者都会犯得错误&#xff0c;当出现这种错误还是比较好排…

STM32的CRC校验(基于HAL库)

一&#xff1a;CRC概念 1&#xff1a;什么是CRC crc是一种纠错技术&#xff0c;代表循环冗余校验&#xff0c;是数据通信领域中最常用的一种差错校验码&#xff0c;其信息字段和校验长度可以任意指定&#xff0c;但要求通信双方定义的CRC标准一致。主要用来检测或校验数据传输或…

伦理学(Ethics)

讯飞星火 伦理学哲学是一门关于道德问题的科学&#xff0c;旨在系统化和理论化道德思想观点。作为一门独立的哲学分支学科&#xff0c;伦理学的本质是对道德现象进行研究&#xff0c;包括道德意识、道德行为以及道德规范现象等。 伦理学的研究对象广泛&#xff0c;涉及个人的…

生成模型之生成器

生成模 型中网络会被作为一个生成器&#xff08;generator&#xff09;来使用。具体来说&#xff0c;在模型输入时会将一个随机 变量z 与原始输入x一并输入到模型中&#xff0c;这个变量是从随机分布中采样得到。输入时可以采 用向量拼接的方式将x和z一并输入&#xff0c;或在x…

『功能项目』怪物消亡掉落宝箱【17】

本章项目成果展示 我们打开上一篇17销毁怪物蛋的Shaders消融特效的项目&#xff0c; 本章要做的事情是在怪物消亡时掉落一个宝箱功能&#xff0c; 首先在资源商店下载一个宝箱物品 拖拽至场景中 完全解压缩 重命名Box 放进Prefabs预制体文件夹后在场景中删除 增加Box两个组件并…

C++和蓝图混用事件

一、在C中创建动态多播委托 1、UEBpAndCpp_Sender.h //声明一个蓝图可调用的多播委托的类型DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FUEBpAndCpp_Broadcast, int, Param);//创建对象UPROPERTY(BlueprintAssignable)FUEBpAndCpp_Broadcast UEBpAndCpp_Broadcast;注意&…

校园闲置物品销售平台

一、项目概述 Hi&#xff0c;大家好&#xff0c;今天分享的项目是《校园闲置物品销售平台》。 校园闲置物品销售平台&#xff0c;旨在为学生提供一个安全、便捷的交易环境。通过线上发布和浏览商品信息&#xff0c;学生可以快速找到自己需要的物品&#xff0c;同时也能将自己…

缓存分布式一致性问题

缓存一致性问题发生的原因&#xff0c;是在更新数据时数据库和缓存数据的不一致。我们要做到保证缓存的最终一致性。如果数据需要强一致性建议直接查询数据库。 双写模式 双写模式为先写数据库&#xff0c;在写缓存。 进来两个请求&#xff0c;先执行“请求1”的操作写入数据…

C语言 | Leetcode C语言题解之第392题判断子序列

题目&#xff1a; 题解&#xff1a; bool isSubsequence(char* s, char* t) {int n strlen(s), m strlen(t);int f[m 1][26];memset(f, 0, sizeof(f));for (int i 0; i < 26; i) {f[m][i] m;}for (int i m - 1; i > 0; i--) {for (int j 0; j < 26; j) {if (t…

jmeter中上传文件接口,当文件名为中文时出现乱码

1、在jmeter5.1.1中配置上传文件接口&#xff0c;当上传的文件为中文名称时&#xff0c;文件名称会显示乱码如图 2、解决方案是需要更换jmeter/lib/ext文件中的ApacheJMeter_http.jar 包 3、更换jar包经过多次实验&#xff0c;发现有的上传文件接口中文名正常&#xff0c;但是有…

华为云征文|部署RedisStack+可视化操作

目录 1.介绍 1.1 什么是华为云Flexus X实例 1.2 什么是Redis Stack ​编辑 2 准备华为云Flexus应用服务器L实例 3 准备docker环境 4 docker 安装 Redis Stack 4.1拉取镜像 4.2 确认镜像 4.3 启动容器 4.4 放行安全组端口 4.5 操作redis 5 docker compose 配置持久 1.…

【算法】--双指针

文章目录 双指针例题移动零复写零快乐数盛⽔最多的容器有效三角形的个数和为 s 的两个数字三数之和四数之和 双指针 常⻅的双指针有两种形式&#xff0c;⼀种是对撞指针&#xff0c;⼀种是快慢指针。 对撞指针&#xff1a;⼀般⽤于顺序结构中&#xff0c;也称左右指针。 对撞…

python判断语句(三)

下一篇持续更新中… 如有错误欢迎指正&#xff01;&#xff01;&#xff01; 文章目录 前言学习内容 布尔类型和比较运算符布尔类型比较运算符总结 if语句的基本格式if语句的注意点总结案例 if else语句注意点总结案例 if elif else语句注意点总结案例 判断语句的嵌套语法格式…

哪里能够使用Claude-100k?

Claude-100k 是 Anthropic 开发的一个大型语言模型&#xff0c;可以在以下几种方式中使用&#xff1a; Anthropic 官网&#xff1a;可以通过访问 Anthropic 的官方网站来获取 Claude-100k 的使用许可或API访问权限。 API 服务&#xff1a;Claude-100k 也可以通过 API 服务进行…

fastchat与autogen使用要点澄清

说明&#xff1a; 本文重点是想使用autogen构建智能体&#xff0c;并且想要通过加载本地模型来构建&#xff0c;以灵活使用。但是autogen重点是以API调用支持openai, mistral等大模型使用的&#xff0c;对于使用国内的一些模型不是那么友好方便。然后在查找方法的过程中&#x…

ElasticSearch学习笔记(五)Bucket聚合、Metric聚合

文章目录 前言9 项目实战9.3 我周边的酒店9.4 酒店竞价排名 10 数据聚合10.1 聚合的分类10.2 DSL实现聚合10.2.1 Bucket聚合10.2.2 聚合结果排序10.2.3 限定聚合范围10.2.4 Metric聚合 10.3 RestAPI实现聚合10.3.1 API语法10.3.2 业务需求10.3.3 业务实现10.3.4 功能测试 前言 …

人工智能、机器学习和深度学习有什么区别?应用领域有哪些?

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发…

RLHF(带有人类反馈的强化学习)初探

我的目标是&#xff0c;在决策游戏上学习某人风格&#xff0c;可以让人对战“带有某人风格”的AI&#xff0c;比如你可以在这里对战“sky风格的AI”,这样的效果。 我最开始受到的启发来源于xbox的广告《爸爸的幽灵车》&#xff0c;已故人在游戏中留下的速度记录的固定轨迹。 …