超级好用的C++实用库之套接字
💡 需要该C++实用库源码的大佬们,可搜索微信公众号“希望睿智”。添加关注后,输入消息“超级好用的C++实用库”,即可获得源码的下载链接。
概述
C++中的Socket编程是实现网络通信的基础,允许程序通过网络与其他程序交换数据。但Socket编程在Windows和Linux系统上存在一些差异,主要包括如下几点。
1、Linux涉及网络编程的头文件主要为<sys/socket.h>、<netinet/in.h>、<arpa/inet.h>,Windows上的头文件主要为<winsock2.h>。
2、Linux不需要显式初始化和清理操作,Windows需要使用WSAStartup和WSACleanup进行显式初始化和清理操作。
3、Linux通常使用perror()或检查返回值,错误码直接从系统调用返回。Windows一般使用WSAGetLastError()获取错误码,并通过WSASetLastError()设置错误码。
4、Linux使用标准的POSIX数据类型,比如:socklen_t。Windows需要使用特定的类型,比如用SOCKET代替int作为套接字描述符。
新手对以上这些差异不熟悉的话,往往会遇到各种各样的问题。另外,阻塞与非阻塞方式发送和接收数据,接口的使用方式也是完全不一样的。为了屏蔽这些差异,并提供更加易用的接口,我们封装了CHP_Socket类。
CHP_Socket
CHP_Socket类是一个接口类,不需要实例化。因此,我们将构造函数和析构函数声明成了私有的,并提供了若干实用的静态函数。这些静态函数涵盖全局初始化、全局清理、初始化TCP套接字、非阻塞连接、非阻塞发送、非阻塞接收等各种操作。
CHP_Socket类的头文件,可参考下面的示例代码。
#pragma once#ifdef _WIN32#include <winsock2.h>
#else#include <unistd.h>
#endif#include "HP_Types.h"#define HP_SOCKET_E_GENERAL -1
#define HP_SOCKET_E_NOROUTE -2
#define HP_SOCKET_E_UNREACHABLE -3
#define HP_SOCKET_E_NOSERVER -4
#define HP_SOCKET_E_TIMEOUT -5
#define HP_SOCKET_E_WOULDBLOCK 1
#define HP_SOCKET_E_ATLEAST_ONE_BYTE 2#ifdef _WIN32#define HP_SOCKET_INVALID_HANDLE INVALID_SOCKETtypedef SOCKET HP_SOCKET;
#else#define HP_SOCKET_INVALID_HANDLE -1typedef int HP_SOCKET;
#endifclass CHP_Socket
{
public:static int Startup();static int Cleanup();static HP_SOCKET InitTcp(unsigned int uiRecvBufSize = 0, unsigned int uiSendBufSize = 0, bool bNoBlock = true);static HP_SOCKET InitUdp(unsigned int uiRecvBufSize = 0, unsigned int uiSendBufSize = 0, bool bNoBlock = true);static void Deinit(HP_SOCKET &sock);static int SetLinger(HP_SOCKET sock, bool bLinger, unsigned int uiTimeoutSec);static int EnableNoBlock(HP_SOCKET sock, bool bEnable = true);static int EnableReuseAddr(HP_SOCKET sock, bool bEnable = true);static int EnableBroadcast(HP_SOCKET sock, bool bEnable = true);static int SetOption(HP_SOCKET sock, int nOptionName, char *pOption, int nOptionLen);static int GetOption(HP_SOCKET sock, int nOptionName, char *pOption, int &nOptionLen);static int Bind(HP_SOCKET sock, unsigned int uiIP, unsigned short usPort);static int Bind(HP_SOCKET sock, const char *pszIP, unsigned short usPort);static int Listen(HP_SOCKET sock, int nListenNum);static int Accept(HP_SOCKET sock, HP_SOCKET &sockNew);static int Connect(HP_SOCKET sock, unsigned int uiIP, unsigned short usPort);static int Connect(HP_SOCKET sock, const char *pszIP, unsigned short usPort);static int ProbeConnect(HP_SOCKET sock);static int TcpSendSingle(HP_SOCKET sock, char *pBuf, int &nBufLen);static int TcpSendWhole(HP_SOCKET sock, char *pBuf, int nTotalLen, int &nSendedLen);static int TcpSendTimeout(HP_SOCKET sock, char *pBuf, int nBufLen, unsigned int uiTimeoutSec);static int TcpRecvSingle(HP_SOCKET sock, char *pBuf, int &nBufLen);static int TcpRecvWhole(HP_SOCKET sock, char *pBuf, int nTotalLen, int &nRecvedLen);static int TcpRecvWholeUntilKey(HP_SOCKET sock, char *pBuf, int nTotalLen, int &nRecvedLen, const char *pszKey);static int TcpRecvTimeout(HP_SOCKET sock, char *pBuf, int nBufLen, unsigned int uiTimeoutSec);static int UdpSend(HP_SOCKET sock, char *pBuf, int &nBufLen, unsigned int uiIP, unsigned short usPort);static int UdpSend(HP_SOCKET sock, char *pBuf, int &nBufLen, const char *pszIP, unsigned short usPort);static int UdpRecv(HP_SOCKET sock, char *pBuf, int &nBufLen, unsigned int &uiIP, unsigned short &usPort);static int UdpRecv(HP_SOCKET sock, char *pBuf, int &nBufLen, char pszIP[16], unsigned short &usPort);static int GetRemoteAddr(HP_SOCKET sock, unsigned int &uiIP, unsigned short &usPort);static int GetRemoteAddr(HP_SOCKET sock, char pszIP[16], unsigned short &usPort);static int GetLocalAddr(HP_SOCKET sock, unsigned int &uiIP, unsigned short &usPort);static int GetLocalAddr(HP_SOCKET sock, char pszIP[16], unsigned short &usPort);static char *IPUintToStr(unsigned int uiIP, char pszIP[16]);static unsigned int IPStrToUint(const char *pszIP);static unsigned short HostToNetwork(unsigned short usValue);static unsigned int HostToNetwork(unsigned int uiValue);static HP_U64 HostToNetwork(HP_U64 ui64Value);static unsigned short NetworkToHost(unsigned short usValue);static unsigned int NetworkToHost(unsigned int uiValue);static HP_U64 NetworkToHost(HP_U64 ui64Value);static int BindDevice(HP_SOCKET sock, const char *pszNetName = "eth0");private:static int SetRecvBufSize(HP_SOCKET sock, unsigned int uiSize);static int SetSendBufSize(HP_SOCKET sock, unsigned int uiSize);static int PasreErrorCode(int nErrorCode);static int Select(HP_SOCKET sock, unsigned int uiTimeoutSec, bool bCheckWrite);private:CHP_Socket();~CHP_Socket();
};
在头文件的开头部分,我们定义几个错误码。其中,小于0的值表示遇到了错误,大于0的值表示非阻塞模式下未发送完或接收完所有数据。各个错误码具体的含义如下。
HP_SOCKET_E_GENERAL:通用错误。
HP_SOCKET_E_NOROUTE:网络不可达。
HP_SOCKET_E_UNREACHABLE:主机不可达。
HP_SOCKET_E_NOSERVER:服务器拒绝。
HP_SOCKET_E_TIMEOUT:连接超时或收发数据超时。
HP_SOCKET_E_WOULDBLOCK:未连接上,需要继续等待;或未收到数据,需要继续等待;或数据未发送出去,需要继续等待。
HP_SOCKET_E_ATLEAST_ONE_BYTE:收到或者发送了至少一个字节的数据。
接下来,我们将详细介绍CHP_Socket类导出的公共接口。
Startup:全局初始化,应用层在程序开始调用一次即可。返回值为0表示成功,其他为错误码。
Cleanup:全局清理,应用层在程序结束调用一次即可。返回值为0表示成功,其他为错误码。
InitTcp:初始化TCP套接字。参数uiRecvBufSize为接收缓冲区大小,单位为B,传0默认为8KB。参数uiSendBufSize为发送缓冲区大小,单位为B,传0默认为8KB。参数bNoBlock表示是否设置非阻塞模式。成功返回套接字,失败返回HP_SOCKET_INVALID_HANDLE。
InitUdp:初始化UDP套接字,参数与返回值的含义同上。
Deinit:释放socket。参数sock为待释放的套接字,可以是TCP套接字,也可以是UDP套接字。
SetLinger:设置socket的SO_LINGER参数(Windows不支持该接口,会直接返回错误)。参数sock为需要设置的套接字,参数bLinger表示是否启用延迟关闭,参数uiTimeoutSec为延迟关闭的时间,单位为秒。返回值为0表示成功,其他为错误码。
EnableNoBlock:使能socket的非阻塞模式。参数sock为需要设置的套接字,参数bEnable表示是否使能非阻塞模式。返回值为0表示成功,其他为错误码。
EnableReuseAddr:使能socket重复绑定。参数sock为需要设置的套接字,参数bEnable表示是否使能重复绑定。返回值为0表示成功,其他为错误码。
EnableBroadcast:使能socket发送广播信息。参数sock为需要设置的套接字,参数bEnable表示是否使能发送广播信息。返回值为0表示成功,其他为错误码。
SetOption:调用setsockopt设置socket的SOL_SOCKET选项。参数sock为需要设置的套接字,参数snOptionName为选项名称,具体参考setsockopt的optname参数定义。参数pOption为选项值内容,具体参考setsockopt的optvalue参数定义。参数nOptionLen为选项值内容长度,具体参考setsockopt的optlen参数定义。返回值为0表示成功,其他为错误码。
GetOption:调用getsockopt获取socket的SOL_SOCKET选项,参数与返回值的含义同上。
Bind:绑定socket的本地地址。参数sock为需要设置的套接字,参数uiIP或pszIP为绑定的IP地址(网络字节序整数或字符串),参数usPort为绑定的端口。返回值为0表示成功,其他为错误码。
Listen:监听socket的连接。参数sock为需要设置的套接字,参数nListenNum为请求队列的最大连接数。返回值为0表示成功,其他为错误码。
Accept:接受客户端的连接请求。参数sock为已经监听的套接字,参数sockNew为请求连接的客户端套接字,用于传出。返回值为0表示成功,其他为错误码。
Connect:连接指定的服务器地址。参数sock为需要连接的套接字,参数uiIP或pszIP为需要连接的服务器IP地址(网络字节序整数或字符串),参数usPort为需要连接的服务器端口。返回值为0表示连接成功,HP_SOCKET_E_WOULDBLOCK表示正在连接,需要调用ProbeConnect不断探测,其他为错误码。
ProbeConnect:非阻塞模式下探测连接服务器是否成功。参数sock为需要探测连接的套接字。返回值为0表示连接成功,HP_SOCKET_E_WOULDBLOCK表示需要等会继续探测,其他为错误码。
TcpSendSingle:TCP连接发送数据。参数sock为需要发送数据的套接字,参数pBuf为需要发送的数据,参数nBufLen传入时为需要发送数据的长度,传出时为已经发送的数据长度。返回值为0表示成功,HP_SOCKET_E_WOULDBLOCK表示需要等会继续发送,其他为错误码。
TcpSendWhole:tcp连接发送数据,可以从上次已发送的位置继续发送数据。参数sock为需要发送数据的套接字,参数pBuf为需要发送的数据,参数nTotalLen为需要发送数据的总长度,参数nSendedLen传入时为已经发送数据的长度,传出时为最新已经发送的数据长度。返回值为0表示成功,HP_SOCKET_E_WOULDBLOCK表示需要等会继续发送,HP_SOCKET_E_ATLEAST_ONE_BYTE表示发送了至少一个字节的数据,也需要继续发送,其他为错误码。
TcpSendTimeout:TCP连接在指定的超时时间内发送数据。参数sock为需要发送数据的套接字,参数pBuf为需要发送的数据,参数nBufLen为需要发送数据的长度,参数uiTimeoutSec为指定的超时时间,单位为秒。返回值为0表示成功,其他为错误码。
TcpRecvSingle:TCP连接接收数据。参数sock为需要接收数据的套接字,参数pBuf为接收数据的缓存,参数nBufLen传入时为需要接收的数据长度,传出时为已经接收到数据的长度。返回值为0表示成功,HP_SOCKET_E_WOULDBLOCK表示需要等会继续接收,其他为错误码。
TcpRecvWhole:TCP连接接收数据,可以从上次已接收的位置继续接收数据。参数sock为需要接收数据的套接字,参数pBuf为接收数据的缓存,参数nTotalLen为接收数据的总长度,参数nRecvedLen传入时为缓存中已经接收的数据长度,传出时为最新已经接收的数据长度。返回值为0表示成功,HP_SOCKET_E_WOULDBLOCK表示需要等会继续接收,HP_SOCKET_E_ATLEAST_ONE_BYTE表示收到了至少一个字节的数据,也需要继续接收,其他为错误码。
TcpRecvWholeUntilKey:TCP连接接收数据直到指定的字符串为止。参数sock为需要接收数据的套接字,参数pBuf为接收数据的缓存,参数nTotalLen为接收数据的总长度,参数nRecvedLen传入时为缓存中已经接收的数据长度,传出时为最新已经接收的数据长度,参数pszKey为指定的结束字符串,一般用于接收指定的边界。返回值为0表示成功,HP_SOCKET_E_WOULDBLOCK表示需要等会继续接收,HP_SOCKET_E_ATLEAST_ONE_BYTE表示收到了至少一个字节的数据,也需要继续接收,其他为错误码。
TcpRecvTimeout:TCP连接在指定的超时时间内接收数据。参数sock为需要接收数据的套接字,参数pBuf为接收数据的缓存,参数nBufLen为接收数据的长度,参数uiTimeoutSec为指定的超时时间,单位为秒。返回值为0表示成功,其他为错误码。
UdpSend: UDP连接发送数据。参数sock为需要发送数据的套接字,参数pBuf为需要发送的数据,参数nBufLen为传入需要发送数据的长度,返回已经发送数据的长度,参数uiIP或pszIP为发送目标的IP地址(网络字节序整数或字符串),参数usPort为发送目标的端口。返回值为0表示成功,HP_SOCKET_E_WOULDBLOCK表示需要等会继续发送,其他为错误码。
UdpRecv:UDP连接接收数据。参数sock为需要接收数据的套接字,参数pBuf为接收数据的缓存,参数nBufLen传入时为需要接收的数据长度,传出时为已经接收到数据的长度。参数uiIP或pszIP返回接收数据的来源IP地址(网络字节序整数或字符串),参数usPort返回接收数据的来源端口。返回值为0表示成功,HP_SOCKET_E_WOULDBLOCK表示需要等会继续接收,其他为错误码。
GetRemoteAddr:获取套接字的对端IP地址和端口。参数sock为需要获取的套接字,参数uiIP或pszIP表示返回的IP地址(网络字节序整数或字符串),参数usPort表示返回的端口。返回值为0表示成功,其他为错误码。
GetLocalAddr:获取套接字本地绑定的IP地址和端口,参数与返回值的含义同上。
IPUintToStr:将整数型IP地址(网络字节序)转换成字符串型IP地址。参数uiIP为整数型IP地址(网络字节序),参数pszIP为字符串型IP地址,用于传出。返回值为字符串型IP地址,非NULL表示成功,否则失败。
IPStrToUint:将字符串型IP地址转换成整数型IP地址(网络字节序)。参数pszIP为字符串型IP地址,返回值为整数型IP地址(网络字节序),非0表示成功,否则失败。
HostToNetwork:将主机字节序转换成网络字节序,可以是16位无符号整数、32位无符号整数、64位无符号整数。
NetworkToHost:将网络字节序转换成主机字节序,可以是16位无符号整数、32位无符号整数、64位无符号整数。
BindDevice:将套接字绑定到某个设备(该接口仅对Linux有效),该接口一般用于多卡绑定同时发送数据。参数sock为套接字,参数pszNetName为设备的网卡接口名称,默认为"eth0"。返回值为0表示成功,其他为错误码。
总结
Socket编程是实现网络间进程通信的基础技术之一,掌握它等于掌握了网络通信的“语言”。无论是简单的数据传输、文件共享,还是复杂的分布式系统构建,Socket都是不可或缺的知识点。了解Socket编程的底层机制,有助于开发者对网络应用的性能瓶颈进行定位和优化,比如:通过调整缓冲区大小、使用非阻塞IO或异步IO模型等方式提升数据传输效率。
相关文章:
超级好用的C++实用库之套接字
💡 需要该C实用库源码的大佬们,可搜索微信公众号“希望睿智”。添加关注后,输入消息“超级好用的C实用库”,即可获得源码的下载链接。 概述 C中的Socket编程是实现网络通信的基础,允许程序通过网络与其他程序交换数据。…...
C++ | Leetcode C++题解之第108题将有序数组转换为二叉搜索树
题目: 题解: class Solution { public:TreeNode* sortedArrayToBST(vector<int>& nums) {return helper(nums, 0, nums.size() - 1);}TreeNode* helper(vector<int>& nums, int left, int right) {if (left > right) {return nu…...
5月27日,每日信息差
第一、韩国宇宙航空厅于 5 月 27 日正式成立,旨在推动以民间为主的太空产业生态圈发展,助力韩国成为航天强国。首任厅长尹宁彬表示,该机构将在庆尚南道泗川市的临时大楼开展相关工作。 第二、京东集团宣布,自2024年7月1日起&…...
echart扩展插件词云echarts-wordcloud
echart扩展插件词云echarts-wordcloud 一、效果图二、主要代码 一、效果图 二、主要代码 // 安装插件 npm i echarts-wordcloud -Simport * as echarts from echarts; import echarts-wordcloud; //下载插件echarts-wordcloud import wordcloudBg from /components/wordcloudB…...
解决无法直接抓取链接地址
当我们在爬取一些文章列表的时候,可能无法从接口或者html界面上获取到文章的详细列表 这个时候我们可以通过模拟点击且重写window.open方法,将跳转的地址捕获,并且放到html中去。 这样我们就可以获取到某个文章的详细地址了 // 保存原始的 …...
java面对对象编程-多态
介绍 方法的多态 多态是在继承,重载,重写的基础上实现的 我们可以看看这个代码 package b;public class main_ {public static void main(String[] args) { // graduate granew graduate(); // gra.cry();//这个时候,子类的cry方法就重写…...
【Sql Server】随机查询一条表记录,并重重温回顾下自定义函数的封装和使用
大家好,我是全栈小5,欢迎来到《小5讲堂》。 这是《Sql Server》系列文章,每篇文章将以博主理解的角度展开讲解。 温馨提示:博主能力有限,理解水平有限,若有不对之处望指正! 目录 前言随机查询语…...
基于C#开发web网页管理系统模板流程-主界面管理员录入和编辑功能完善
前言 紧接上篇->基于C#开发web网页管理系统模板流程-登录界面和主界面_c#的网页编程-CSDN博客 已经完成了登录界面和主界面,本篇将完善主界面的管理员录入和编辑功能,事实上管理员录入和编辑的设计套路适用于所有静态表的录入和编辑 首先还是介绍一下…...
K8s证书过期处理
问题描述 本地有一个1master2worker的k8s集群,今天启动VMware虚拟机之后发现api-server没有起来,docker一直退出,这个集群是使用kubeadm安装的。 于是kubectl logs查看了日志,发现证书过期了 解决方案: 查看证书 #…...
刷题之路径总和Ⅲ(leetcode)
路径总和Ⅲ 这题和和《为K的数组》思路一致,也是用前缀表。 代码调试过,所以还加一部分用前序遍历数组和中序遍历数组构造二叉树的代码。 #include<vector> #include<unordered_map> #include<iostream> using namespace std; //Def…...
MongoDB 原子操作:确保数据一致性和完整性的关键
在 MongoDB 中,原子操作是指可以一次性、不可分割地执行的数据库操作。这些操作能够保证在多个并发操作中不会出现数据不一致或者丢失的情况,确保数据库的数据完整性和一致性。 基本语法 MongoDB 的原子操作通常与更新操作相关,其基本语法如…...
2024上半年软考高级系统架构设计师回顾
本博客地址:https://security.blog.csdn.net/article/details/139238685 2024年上半年软考在5月25-26日举行,趁着时间刚过去记忆还在,简单写一点总结。 关于考试形式:上机考试(以后也都是机考)࿰…...
SQL注入绕过技术深度解析与防御策略
引言 在Web安全领域,SQL注入攻击一直是一个棘手的问题。攻击者通过SQL注入手段获取敏感数据、执行恶意操作,甚至完全控制系统。尽管许多防御措施已被广泛采用,但攻击者仍不断开发新的绕过技术。本文将深度解析SQL注入的绕过技术,…...
Redis教程(十六):Redis的缓存穿透、缓存击穿、缓存雪崩
传送门:Redis教程汇总篇,让你从入门到精通 缓存穿透 描述 用户需要查询一个数据,例如要查一张ASSET_CODE 999999的卡片,查询redis中没有,就直接去请求数据库,数据库中也不存在对应的数据,返回…...
如何实现一个高效的单向链表逆序输出?
实现单向链表逆序输出的关键点有两个: 反转链表本身 遍历反转后的链表并输出首先,我们来看如何反转链表: class Node:def __init__(self, data):self.data dataself.next Nonedef reverse_list(head):"""反转单向链表"""prev Nonecurrent h…...
使用 Go 实现 HelloWorld 程序,并分析其结构
在学习任何新的编程语言时,编写一个 “Hello, World” 程序通常是最初的入门步骤。这不仅是一个传统,也是一种快速了解语言基本语法和运行机制的有效方法。对于 Go 语言,这个过程不仅可以帮助新手快速入门,还提供了一个窗口&#…...
机器学习:在Python中sklearn库的使用,纯干货!12个小时的整理!
无监督学习是在没有标签的数据上训练的。其主要目的可能包括聚类、降维、生成模型等。 以下是 6 个重要的无监督学习算法,这些算法都可以通过使用sklearn(Scikit-learn)库在Python中很好地处理: 目录 K-Means 聚类 层次聚类 …...
XSS 攻击
XSS 攻击简介 定义: XSS(跨站脚本攻击)是一种网络安全漏洞,攻击者通过在 Web 页面中注入恶意代码,利用用户的浏览器执行这些恶意脚本,从而实施攻击。 解决方案: 过滤用户输入: 对…...
.Net Core 中间件与过滤器
过滤器这个是.Net MVC旧有的功能,中间件这个概念是新出的, ASP.NET Core只是完成了HTTP请求调度、报文解析等必要的工作,像检查用户身份、设置缓存报文头等操作都是在中间件中完成,中间件就是ASP.NET Core的一个组件,…...
【ARMv7-A】——WFI(wait for interrupt)
文章目录 WFI基本原理使用场景多任务模型注意事项代码实例linux 内核中的 WFI 指令不使用 WFI 指令测试使用 WFI 指令测试WFI WFI 即 Wait for interrupt,常用于低功耗。 WFI (Wait for interrupt) 和 WFE (Wait for event) 是两个让 ARM 核进入 low-power standby 模式的指…...
如何使用Photon光影包提升Minecraft视觉体验
如何使用Photon光影包提升Minecraft视觉体验 【免费下载链接】photon A gameplay-focused shader pack for Minecraft 项目地址: https://gitcode.com/gh_mirrors/photon3/photon Photon光影包是一款专注于游戏体验的Minecraft光影解决方案,通过先进的光照算…...
【Ubuntu20.04】libudev-dev依赖冲突排查与修复指南
1. 遇到libudev-dev安装问题怎么办? 最近在Ubuntu 20.04上安装libudev-dev时,你是不是也遇到了烦人的依赖冲突?作为一个长期使用Ubuntu的老用户,我完全理解这种挫败感。记得我第一次遇到这个问题时,系统提示"无法…...
基于深度学习的FasterRCNN水下图像复原
项目概述:Waternet_FasterRCNN 本项目旨在结合深度学习技术进行水下图像的还原与分析,综合应用 WaterNet 和 Faster R-CNN 来完成以下功能: 水下图像还原:利用 WaterNet 修复和增强水下图像质量。色板检测与提取:通过 …...
深入解析Xilinx FPGA中的IDDR与ODDR原语:从原理到实践
1. 认识FPGA中的DDR采样难题 在高速数据采集和传输领域,双倍数据速率(DDR)技术已经成为标配。想象一下你正在用AD9361这类射频收发器与FPGA通信,数据时钟频率轻松达到数百MHz。这时候如果还沿用传统的单沿采样,就像用单…...
基于DRAMsim3的扩散模型训练加速仿真:内存时延与能耗分析
基于DRAMsim3的扩散模型训练加速仿真:内存时延与能耗分析 摘要 扩散模型在生成式AI领域取得了巨大成功,但其训练过程极其昂贵,主要体现在对内存带宽的巨大需求(尤其是Attention机制和梯度存储)。本文聚焦于利用DRAMsim3模拟器,在系统架构层面仿真扩散模型(如DDPM)训练…...
别再只盯着Protobuf了!从DDS到Thrift,聊聊不同IDL在自动驾驶和机器人项目里的真实选型
自动驾驶与机器人系统中的IDL选型实战:从DDS到Thrift的深度解析 在自动驾驶和机器人系统的开发中,接口定义语言(IDL)的选择往往决定了整个通信架构的成败。当激光雷达每秒产生数十万点云数据,当多个传感器需要在毫秒级完成数据融合ÿ…...
微生物网络分析参数配置与结果验证:microeco中SpiecEasi的进阶应用指南
微生物网络分析参数配置与结果验证:microeco中SpiecEasi的进阶应用指南 【免费下载链接】microeco An R package for data analysis in microbial community ecology 项目地址: https://gitcode.com/gh_mirrors/mi/microeco 在微生物生态学研究中,…...
UniApp多商户小程序自动化发布:基于Jenkins与miniprogram-ci的SaaS化部署实践
1. 为什么需要自动化发布多商户小程序? 做过SaaS平台的朋友都知道,当你的平台上有成百上千个商户,每个商户都需要独立的小程序时,手动发布简直就是一场噩梦。我去年接手的一个电商SaaS项目,平台上有300多家商户&#x…...
Mac 安装 Java JDK 完整教程:一篇文章讲透安装、配置、多版本管理
一、Java JDK 详解1.1 什么是 JDK?JDK(Java Development Kit,Java 开发工具包)是 Oracle 公司提供的用于 Java 程序开发的完整软件包。它是 Java 开发者不可或缺的核心工具,包含了编写、编译、调试和运行 Java 程序所需…...
Winhance中文版:图形化系统优化工具让Windows用户实现高效系统管理与个性化定制
Winhance中文版:图形化系统优化工具让Windows用户实现高效系统管理与个性化定制 【免费下载链接】Winhance-zh_CN A Chinese version of Winhance. C# application designed to optimize and customize your Windows experience. 项目地址: https://gitcode.com/g…...
