KRTS网络模块:UDP通信

2024-09-04 07:04
文章标签 模块 udp 网络 通信 krts

本文主要是介绍KRTS网络模块:UDP通信,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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%。整体来看,大部分抖动集中在低值区间,表明系统具有较好的时间稳定性和可预测性。测试过程中不同硬件的测试结果会产生较大差异。

这篇关于KRTS网络模块:UDP通信的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1135333

相关文章

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

python中的与时间相关的模块应用场景分析

《python中的与时间相关的模块应用场景分析》本文介绍了Python中与时间相关的几个重要模块:`time`、`datetime`、`calendar`、`timeit`、`pytz`和`dateu... 目录1. time 模块2. datetime 模块3. calendar 模块4. timeit

Python模块导入的几种方法实现

《Python模块导入的几种方法实现》本文主要介绍了Python模块导入的几种方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录一、什么是模块?二、模块导入的基本方法1. 使用import整个模块2.使用from ... i

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

ASIO网络调试助手之一:简介

多年前,写过几篇《Boost.Asio C++网络编程》的学习文章,一直没机会实践。最近项目中用到了Asio,于是抽空写了个网络调试助手。 开发环境: Win10 Qt5.12.6 + Asio(standalone) + spdlog 支持协议: UDP + TCP Client + TCP Server 独立的Asio(http://www.think-async.com)只包含了头文件,不依

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

poj 3181 网络流,建图。

题意: 农夫约翰为他的牛准备了F种食物和D种饮料。 每头牛都有各自喜欢的食物和饮料,而每种食物和饮料都只能分配给一头牛。 问最多能有多少头牛可以同时得到喜欢的食物和饮料。 解析: 由于要同时得到喜欢的食物和饮料,所以网络流建图的时候要把牛拆点了。 如下建图: s -> 食物 -> 牛1 -> 牛2 -> 饮料 -> t 所以分配一下点: s  =  0, 牛1= 1~