linux网络编程6——基于UDP的可靠传输协议KCP/QUIC

文章目录

  • 基于UDP的可靠传输协议KCP/QUIC
    • 1 KCP基本原理
      • 1.1 如何做到可靠传输
      • 1.2 TCP和UDP如何选择
      • 1.3 ARQ协议
        • 1.3.1 停止等待ARQ
        • 1.3.2 回退nARQ
        • 1.3.3 选择重传ARQ
      • 1.4 RTT和RTO
      • 1.5 流量控制——滑动窗口
      • 1.6 拥塞控制
      • 1.7 KCP协议的优势
        • 1.7.1 RTO翻倍 vs 不翻倍
        • 1.7.2 选择重传 vs 全部重传
        • 1.7.3 快速重传
        • 1.7.4 延迟ACK vs 非延迟ACK
        • 1.7.5 UNA vs ACK + UNA
        • 1.7.6 非退让流控
    • 2. KCP源码分析和使用
      • 2.1 名词说明
      • 2.2 kcp协议头
        • 2.2.1 ikcp中的主要数据结构
      • 2.2 KCP的使用方式
        • 2.2.1 生成会话ID
        • 2.2.2 流程
        • 2.2.3 KCP配置模式
    • 3. 重点问题
    • 4. QUIC简介
      • 4.1 QUIC 的核心特点
    • 学习参考

基于UDP的可靠传输协议KCP/QUIC

本文详细介绍了KCP协议基本原理,并简要介绍了KCP的使用方式以及QUIC协议。

1 KCP基本原理

1.1 如何做到可靠传输

可靠传输最主要是依赖于ARQ协议,即自动重复请求协议,它的基本功能是在丢包时请求重传,它的如下机制保证了可靠的传输:

  • ACK确认机制,确保数据已被接收。

  • 重传机制,当超时或者判断丢包时重传数据。

  • 序号机制,检测是否有数据丢失和是否有序。

  • 重排机制,使乱序到达的数据重新有序。

1.2 TCP和UDP如何选择

以下是一个总结UDP和TCP之间主要区别的表格:

特性TCPUDP
连接方式面向连接(建立连接)无连接(无需建立连接)
传输方式面向字节流面向报文
可靠性提供可靠的数据传输(数据包顺序、重传机制)不保证可靠性(可能丢失数据包)
数据顺序确保数据包按顺序到达不保证数据包顺序
流控制提供流控制(使用滑动窗口协议)不提供流控制
拥塞控制提供拥塞控制机制不提供拥塞控制
适用场景适合需要可靠传输的应用(如网页、文件传输)适合实时应用(如视频、语音);游戏行业
传输速率相对较慢(由于连接管理、错误校正)相对较快(无连接管理、简单)
应用协议HTTP, FTP, SMTP 等DNS, DHCP, VoIP 等

字节流: 连续、有序。

报文:离散,无序。

1.3 ARQ协议

ARQ(Automatic Repeat reQuest),即自动重复请求,是一种确保可靠传输的机制。可以参考这篇博文详细了解。

1.3.1 停止等待ARQ

很少被采用。

1.3.2 回退nARQ

TCP采用这种重传机制。ARQ

1.3.3 选择重传ARQ

KCP采用这种方式。

1.4 RTT和RTO

RTO(Retransmission TimeOut)即重传超时时间

RTT(Round-Trip Time)即往返时延

1.5 流量控制——滑动窗口

为什么要进行流量控制:发送方的发送速率与接收方的接受速率存在差异

  1. 如果发送方速率大于接收方速率,接收方就不得不丢弃很多数据包,导致传输效率下降。
  2. 如果发送方速率小于接收方速率,会浪费带宽。

怎么进行流量控制:滑动窗口

接收方会告诉发送方自己的接收窗口的大小,还能够接收多少数据,这样发送方知道能够发送多少数据。

其他小问题总结

  • 接收窗口大小固定吗?不固定,需要根据网络情况动态调整。
  • 接收窗口越大越好吗?不是,接收窗口过大容易导致乱序和丢包。
  • 发送窗口和接收窗口相等吗?一般接收窗口>=发送窗口。

1.6 拥塞控制

主要由四个算法组成:

  • 慢启动
  • 拥塞避免
  • 快速恢复 (TCP Reno版本开始使用)
  • 快速重传

简要了解可以参考我的博文,详细了解可以参考这篇博文。

1.7 KCP协议的优势

在不稳定的网络中,KCP以10%-20%带宽浪费的代价,换取比TCP快30%-40%的传输速度

在网络通畅的情况下,文件传输速度上,kcp < tcp。

KCP的传输速度优势本质上来自于其实现的ARQ协议的重传策略。它通过以下机制实现了这样的目标:

  • 尽量减少重传超时等待的时间(即RTO)。
  • 尽量减少丢包的成本(得益于选择重传ARQ)。

尽管实现这样的目标是以消耗的网络带宽增加为代价的。

1.7.1 RTO翻倍 vs 不翻倍

TCP的超时时长计算策略是翻倍,而KCP启动快速模式后是乘以1.5,提高了传输速度。

KCP还可以定制重传策略定制丢包策略

1.7.2 选择重传 vs 全部重传

KCP使用选择拒绝自动重复请求,只重传那些已经丢失的包。

KCP使用快速重传,KCP的快速重传是指当发现某个数据段被跳过确认多次后,不必等待RTO而直接重传,大大改善了丢包时的重传速度。

1.7.3 快速重传

发送端发送了1,2,3,4,5几个包,然后收到远端的ACK: 1, 3, 4, 5,当收到ACK3时,KCP知道2被跳过1次,收到ACK4时,知道2被跳过了2次,此时可以认为2号丢失,不用等超时,直接重传2号包,大大改善了丢包时的传输速度。

1.7.4 延迟ACK vs 非延迟ACK

TCP为了充分利用带宽,选择延迟发送ACK,这样超时计算会算出较大的RTT时间,从而延长了RTO时间。而KCP的ACK是否延迟可以调节。

在TCP中,一个ACK可以确认多个数据段,因此采用延迟ACK可以减少网络包数量。

1.7.5 UNA vs ACK + UNA

ARQ的响应模式有两种,UNA(Unacknowledged Number Acknowledged)和ACK,UNA模式下确认序号指的是下一个期待收到的序号,ACK模式下确认序号指的是已经收到的数据段的序号。只用UNA会导致太多重传,只用ACK会导致丢失成本太高(ACK包丢失可能会导致不必要的重传)。在KCP协议中,除去单独的ACK包外,所有的包都有UNA信息。

1.7.6 非退让流控

KCP正常模式下通TCP一样使用公平退让法则,即发送窗口大小由:发送缓存大小、接收端窗口大小、丢包退让、拥塞窗口这四个因素决定。当采用非退让流控时,就不考虑后两个因素。

2. KCP源码分析和使用

2.1 名词说明

MTU: 最大传输单元,是数据链路层的概念,以太网为1500字节。实际在传输层考虑到PDU的消耗,使用1400字节比较合适。

cwnd:拥塞窗口大小

rwnd:接收方窗口大小

snd_queue:待发送KCP数据包的队列

snd_buf:发送缓冲区

snd_nxt:下一个即将发送的kcp数据包序列号

snd_una:下一个待确认的序列号

2.2 kcp协议头

0                            4               6           8  (BYTE)
+----------------------------+---------------+-----------+
|            conv            | cmd   |  frg  |    wnd    | 8   
+----------------------------+---------------+-----------+
|            ts              |            sn             | 16
+----------------------------+---------------------------+
|            una             |            len            | 24
+----------------------------+---------------------------+
|                        DATA (optional)                 |
+--------------------------------------------------------+
  • conv: 会话标识
  • cmd: 命令,如IKCP_CMD_ACK
  • frg: 分片标识
  • wnd: 接收窗口大小
  • ts: 时间序列
  • sn: 序列号
  • una: 下一个期待的数据序列号
  • len: 数据长度
  • data: 数据
2.2.1 ikcp中的主要数据结构
  • ikcp控制块,类似与tcp中的tcp控制块,保存每个kcp会话的核心数据。
struct IKCPCB
{/* 会话状态信息 */IUINT32 conv;   // 标识会话IUINT32 mtu;    // 最大传输单元,默认数据为1400,最小为50IUINT32 mss;    // 最大分片大小,不大于mtuIUINT32 state;  // 连接状态(0xffffffff表示断开连接)int nocwnd;     // 取消拥塞控制int stream;     // 是否采用流传输模式int logmask;    // 日志的类型,如IKCP_LOG_IN_DATA,方便调试/* 用于ARQ的字段 */IUINT32 snd_una;    // 第一个未确认的包IUINT32 snd_nxt;    // 下一个待分配包的序号IUINT32 rcv_nxt;	// 待接收消息序号IUINT32 ts_recent;	// 最近收到的数据的时间  IUINT32 ts_lastack;	// 上一个收到的ACK的时间IINT32  rx_rttval;      // RTT的变化量,代表连接的抖动情况IINT32  rx_srtt;        // smoothed round trip time,平滑后的RTT;IINT32  rx_rto;         // 收ACK接收延迟计算出来的重传超时时间IINT32  rx_minrto;      // 最小重传超时时间IUINT32 *acklist;   //待发送的ack的列表。当收到一个数据报文时,将其对应的ACK报文的 sn 号以及时间戳 ts 同时加入到acklist 中,即形成如 [sn1, ts1, sn2, ts2 …] 的列表/* 滑动窗口 */struct IQUEUEHEAD snd_queue;    //发送消息的队列 struct IQUEUEHEAD rcv_queue;    //接收消息的队列, 是已经确认可以供用户读取的数据struct IQUEUEHEAD snd_buf;      //发送消息的缓存 和snd_queue有什么区别struct IQUEUEHEAD rcv_buf;      //接收消息的缓存, 还不能直接供用户读取的数据/* 拥塞控制 */IUINT32 ssthresh;       // 拥塞窗口的阈值IUINT32 cwnd;           // 拥塞窗口大小, 动态变化...;int (*output)(const char *buf, int len, struct IKCPCB *kcp, void *user);//发送消息的回调函数void (*writelog)(const char *log, struct IKCPCB *kcp, void *user);  // 写日志的回调函数
}
  • ikcp每个分片的数据结构
struct IKCPSEG
{struct IQUEUEHEAD node;IUINT32 conv;   // 会话编号,和TCP的con一样,确保双方需保证conv相同,相互的数据包才能被接收.conv唯一标识一个会话IUINT32 cmd;    // 区分不同的分片.IKCP_CMD_PUSH数据分片;IKCP_CMD_ACK:ack分片;IKCP_CMD_WASK:请求告知窗口大小;IKCP_CMD_WINS:告知窗口大小IUINT32 frg;    // 标识segment分片ID,用户数据可能被分成多个kcp包发送, 为0时代表   IUINT32 wnd;    // 剩余接收窗口大小(接收窗口大小-接收队列大小),发送方的发送窗口不能超过接收方给出的数值IUINT32 ts;     // 发送时刻的时间戳IUINT32 sn;     // 分片segment的序号,按1累加递增IUINT32 una;    // 待接收消息序号(接收滑动窗口左侧).对于未丢包的网络来说,una是下一个可接收的序号,如收到sn=10的包,una为11IUINT32 len;    // 数据长度IUINT32 resendts;   // 下次超时重传时间戳IUINT32 rto;        //该分片的超时等待时间,其计算方法同TCPIUINT32 fastack;    // 收到ack时计算该分片被跳过的累计次数,此字段用于快速重传,自定义需要几次确认开始快速重传IUINT32 xmit;       // 发送分片的次数,每发一次加1.发送的次数对RTO的计算有影响,但是比TCP来说,影响会小一些.char data[1];
};

2.2 KCP的使用方式

2.2.1 生成会话ID

会话ID用来标识客户端与服务器端的一条逻辑连接。

两种方式:

  • 客户端使用随机数产生uuid。
  • 服务器端产生唯一id然后通过http协议等传给客户端。

ikcp中的实现:

// read conv 获取会话id
IUINT32 ikcp_getconv(const void *ptr)
{IUINT32 conv;ikcp_decode32u((const char*)ptr, &conv);return conv;
}/* decode 32 bits unsigned int (lsb) */
static inline const char *ikcp_decode32u(const char *p, IUINT32 *l)
{
#if IWORDS_BIG_ENDIAN || IWORDS_MUST_ALIGN*l = *(const unsigned char*)(p + 3);*l = *(const unsigned char*)(p + 2) + (*l << 8);*l = *(const unsigned char*)(p + 1) + (*l << 8);*l = *(const unsigned char*)(p + 0) + (*l << 8);
#else memcpy(l, p, 4);
#endifp += 4;return p;
}

每个会话都对应一个kcp控制块,会话在构造时也会设置ikcpcb中的output回调函数,这样只需要封装号session类,用户就只需要与session打交道了。

2.2.2 流程
  • 创建KCP对象
ikcpcb *kcp = ikcp_create(conv, user);
  • 设置发送回调函数(如UDP的send函数)
kcp->output = udp_output;
  • 循环调用update
ikcp_update(kcp, millisec);	// 在一个线程、定时器5ms/10ms做调度
  • 输入一个应用层数据包(如UDP收到的数据包)
ikcp_input(kcp, received_udp_packet, received_udp, size);
  • 发送数据
ikcp_send(kcp1, buffer, 8);
  • 接收数据
hr = ikcp_recv(kcp2, buffer, 10);

需要注意,接收数据时需要用户先用UDP socket的API读取出数据,然后调用ikcp_input(),然后再调用ikcp_recv()。

2.2.3 KCP配置模式

工作模式

int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc)
  • nodelay: 是否开启ACK延迟确认,0不启用,1启用
  • interval: 协议内部工作工作的interval,单位ms,默认10ms
  • resend:是否开启快速重传模式,默认不开启
  • nc:是否关闭流控,默认不关闭

最大窗口

int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd);	// 默认32

最大传输单元:

int ikcp_setmtu(ikcpcb *kcp, int mtu);	// 默认1400

最小RTO:

kcp->rx_minrto = 10;	// 快速模式下为30ms,可以手动更改

3. 重点问题

  1. tcp为什么可靠?

tcp的可靠性来自于滑动窗口和ARQ协议,它们保证了数据不丢失、不乱序。

  1. kcp为什么牺牲带宽换取速度?

kcp适用于对实时通讯要求较高的场景,例如直播、网络游戏等领域。它基于UDP协议,省去了三次握手的过程。kcp使用了自定义重传机制(如RTO、快速重传)、自定义是否启用拥塞控制,选择决绝ARQ也降低了重传成本。因此综合来看,kcp增加了网络中数据包的数量,但是提高了数据包的实时性。在不稳定的网络环境下,kcp的优势更为明显。

  1. udp怎么实现客户端和服务端编程?服务端怎么维护和客户端的逻辑连接?

UDP不能像tcp那样建立连接并长时间维持上下文信息,而只能通过每个数据包来源的目的地址和端口识别对方。为了维护逻辑连接,通常服务端可以使用一个具有唯一ID的会话保存特定客户端的信息。这个会话机制包括:

  • 客户端标识
  • 状态管理
  • 心跳机制

4. QUIC简介

QUIC(Quick UDP Internet Connections)是一种基于 UDP 的传输层协议,由 Google 开发,旨在为网络通信提供更快、更可靠的体验。QUIC 的设计目标是在保持低延迟的同时,提供与 TCP 相似的可靠性和拥塞控制,并解决一些传统 TCP 和 TLS 协议的缺点,比如慢启动、连接延迟高等问题。

4.1 QUIC 的核心特点

  • 低延迟连接建立

QUIC 通过将握手和加密合并到一个过程,使客户端和服务端能够在一次往返(1-RTT)中完成握手。对于已经建立过连接的客户端,QUIC 还支持 0-RTT 握手,这意味着客户端可以在发送初始请求的同时发送数据,极大地减少了连接延迟。

  • 集成的 TLS 加密

QUIC 将 TLS 1.3 协议集成在其协议栈中,从而在连接开始时即提供加密通信。这种方式不仅能提高连接安全性,还避免了传统 TCP 和 TLS 分别握手带来的延迟。

  • 多路复用

传统 TCP 实现 HTTP/2 的多路复用时,存在着“队头阻塞”问题(某个流的丢包会阻塞其他流的数据传输)。QUIC 通过流的独立处理机制,使每个流都可以独立地进行数据传输,避免了队头阻塞的情况。

  • 灵活的拥塞控制

QUIC 的拥塞控制算法可由实现方选择或配置,这使得它更具灵活性,可以根据网络情况灵活调整,进一步提高传输效率和稳定性。此外,QUIC 的流量控制机制可以控制流级别的数据量,以防止客户端或服务端被大量数据淹没。

  • 基于 UDP

QUIC 通过 UDP 实现,不受操作系统内核中 TCP 堆栈限制的影响,便于快速更新和改进协议,特别适合现代互联网的需求。

学习参考

学习更多相关知识请参考零声 github。

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

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

相关文章

表格编辑demo

<el-form :model"form" :rules"status ? rules : {}" ref"form" class"form-container" :inline"true"><el-table :data"tableData"><el-table-column label"计算公式"><templat…

ArcGIS001:ArcGIS10.2安装教程

摘要&#xff1a;本文详细介绍arcgis10.2的安装、破解、汉化过程。 一、软件下载 安装包链接&#xff1a;https://pan.baidu.com/s/1T3UJ7t_ELZ73TH2wGOcfpg?pwd08zk 提取码&#xff1a;08zk 二、安装NET Framework 3.5 双击打开控制面板&#xff0c;点击【卸载程序】&…

05方差分析续

文章目录 1.Three way ANOVA2.Latin square design2.Hierarchical (nested) ANOVA3.Split-plot ANOVA4.Repeated measures ANOVA5.Mixed effect models 1.Three way ANOVA 三因素相关分析 单因子分析的代码 data(mtcars) nrow(mtcars) # 32 mtcars$cyl as.factor(mtcars$cyl…

c#子控件拖动父控件方法及父控件限在窗体内拖动

一、效果 拖放位置不超过窗体四边,超出后自动靠边停靠支持多子控件拖动指定控件拖放(含父控件或窗体)点击左上角logo弹出消息窗口(默认位置右下角)1.1 效果展示 1.2 关于MQTTnet(最新版v4.3.7.1207)实现在线客服功能,见下篇博文 https://github.com/dotnet/MQTTnet 网上…

BIO,NIO,直接内存,零拷贝

前置知识 什么是Socket&#xff1f; Socket是应用层与TCP/IP协议族通信的中间软件抽象层&#xff0c;它是一组接口&#xff0c;一般由操作系统提供。在设计模式中&#xff0c;Socket其实就是一个门面模式&#xff0c;它把复杂的TCP/IP协议处理和通信缓存管理等等都隐藏在Sock…

莱维飞行(Levy Flight)机制的介绍和MATLAB例程

文章目录 莱维飞行机制算法简介自然现象中的应用优化问题中的应用关键公式 MATLAB代码示例代码说明运行结果 莱维飞行机制算法的应用前景1. 自然科学中的应用2. 计算机科学中的应用3. 工程技术中的应用4. 金融与经济学中的应用5. 医疗与生物信息学中的应用6. 未来研究方向 结论…

【软件工程】软件工程入门

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;软件开发必练内功_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前…

软件分享丨Marktext 编辑器

Marktext是一款开源免费的Markdown编辑器&#xff0c;它具有简洁优雅的界面设计和强大的功能&#xff0c;支持多种Markdown语法&#xff0c;包括表格、流程图、甘特图、数学公式、代码高亮等。Marktext还支持导出HTML和PDF格式的文档&#xff0c;非常适合需要编写Markdown文档的…

5G NR:BWP入门

简介 5G NR 系统带宽比4G LTE 大了很多&#xff0c;4G LTE 最大支持带宽为20MHz&#xff0c; 而5G NR 的FR1 最大支持带宽为100MHz&#xff0c; FR2 最大支持带宽为 400MHz。 带宽越大&#xff0c;意味了终端功耗越多。为了减少终端的功耗&#xff0c;5G NR 引入了BWP(Band Wid…

不写单元测试的我,被批了

最近在看单元测试的东西&#xff0c;想跟大家聊聊我的感受。单元测试这块说实在的&#xff0c;我并不太熟悉&#xff0c;我几乎不写单元测试&#xff0c;也不太爱写单元测试。 当我推广消息推送平台austin的时候&#xff0c;有过批评我整个项目没有单元测试&#xff0c;也有过…

《a16z : 2024 年加密货币现状报告》解析

加密社 原文链接&#xff1a;State of Crypto 2024 - a16z crypto译者&#xff1a;AI翻译官&#xff0c;校对&#xff1a;翻译小组 当我们两年前第一次发布年度加密状态报告的时候&#xff0c;情况跟现在很不一样。那时候&#xff0c;加密货币还没成为政策制定者关心的大事。 比…

生信软件39 - GATK最佳实践流程重构,提高17倍分析速度的LUSH流程

1. LUSH流程简介 基因组测序通常用于分子诊断、分期和预后&#xff0c;而大量测序数据在分析时间方面提出了挑战。 对于从FASTQ到VCF的整个流程&#xff0c;LUSH流程在非GVCF和GVCF模式下都大大降低了运行时间&#xff0c;30 X WGS数据耗时不到2 h&#xff0c;从BAM到VCF约需…

使用 ASP.NET Core 8.0 创建最小 API

构建最小 API&#xff0c;以创建具有最小依赖项的 HTTP API。 它们非常适合需要在 ASP.NET Core 中仅包括最少文件、功能和依赖项的微服务和应用。 本教程介绍使用 ASP.NET Core 生成最小 API 的基础知识。 在 ASP.NET Core 中创建 API 的另一种方法是使用控制器。 有关在最小 …

认识CSS语法

CSS&#xff08;网页美容&#xff09; 重点&#xff1a;选择器、盒子模型、浮动、定位、动画&#xff0c;伸缩布局 Css的作用&#xff1a; 美化网页&#xff1a;CSS控制标签的样式 网页布局&#xff1a;CSS控制标签的位置 概念&#xff1a;层叠样式表&#xff08;级联样式表…

Maven(解决思路)

1.前言 作为一名一线的开发人员&#xff0c;maven大概率是我们用的最多的依赖管理&#xff0c;但是你知道我们的maven出现问题后怎么去排查么&#xff1f;不对&#xff0c;确切的来说&#xff0c;假如你去导入的包没有被成功导入&#xff0c;你有什么方法去排查、去解决这个问题…

Linux-Centos操作系统备份及还原(整机镜像制作与还原)--再生龙

适用场景 Linux系统设备需要备份整机数据&#xff0c;或者需要还原到多台设备上。适用再生龙工具进行整机备用和还原。 镜像制作 下载再生龙镜像&#xff1a;clonezilla-live-2.6.4-10-amd64.iso&#xff0c;制作启动盘-设置U盘启动 启动后界面如下选择第四项other modes of…

力扣143:重排链表

给定一个单链表 L 的头节点 head &#xff0c;单链表 L 表示为&#xff1a; L0 → L1 → … → Ln - 1 → Ln请将其重新排列后变为&#xff1a; L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → … 不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的进行节点交换。 示…

如何使用的是github提供的Azure OpenAI服务

使用的是github提供的Azure OpenAI的服务gpt-4o 说明&#xff1a;使用的是github提供的Azure OpenAI的服务&#xff0c;可以无限薅羊毛。开源地址 进入&#xff1a; 地址 进入后点击 右上角“Get API key”按钮 点击“Get developer key” 选择Beta版本“Generate new to…

HarmonyOS开发 - 本地持久化之实现LocalStorage实例

用户首选项为应用提供Key-Value键值型的数据处理能力&#xff0c;支持应用持久化轻量级数据&#xff0c;并对其修改和查询。数据存储形式为键值对&#xff0c;键的类型为字符串型&#xff0c;值的存储数据类型包括数字型、字符型、布尔型以及这3种类型的数组类型。 说明&#x…

C#通过异或(^)运算符制作二进制加密(C#实现加密)

快速了解异或运算符&#xff1a; 异或运算符在C#中用 “^” 来表示 口诀&#xff1a;相同取0&#xff0c;相异取1 简单加密解密winform示例&#xff1a; /// <summary>/// 异或运算符加密实现/// </summary>/// <param name"p_int_Num">初始值<…