首页 > 系统相关 >5. 从零开始编写一个类nginx工具, 通讯协议建立, 为内网穿透做准备

5. 从零开始编写一个类nginx工具, 通讯协议建立, 为内网穿透做准备

时间:2023-10-28 18:02:18浏览次数:39  
标签:字节 pub nginx 从零开始 u32 长度 内网 服务端 Socket

wmproxy

wmproxy是由Rust编写,已实现http/https代理,socks5代理, 反向代理,静态文件服务器,内网穿透,配置热更新等, 后续将实现websocket代理等,同时会将实现过程分享出来, 感兴趣的可以一起造个轮子法

项目 ++wmproxy++

gite: https://gitee.com/tickbh/wmproxy

github: https://github.com/tickbh/wmproxy

什么是通讯协议?

在tcp的流传输过程中,可以看做是一堆的字节的集合体,是一种“流”式协议,就像河里的水,中间没有边界。或者好比不懂汉语的来看古文,因为古文里没有任何的句读,不知何时另起一行。那我们如何正确的做到拆包解包,保证数据格式的正确呢?

以下是客户端发送两个30字节的包(P1及P2),服务端读取数据可能读出来的可能

5. 从零开始编写一个类nginx工具, 通讯协议建立, 为内网穿透做准备_服务端

若没有事先约定好格式,在服务端部分无法正确的解析出P1包和P2包,也就意味着无法理解客户端发的内容。若此时我们约定每个包的大小固定为30字节,那么2,3,4三种可能不管收到多少,都必须等待30字节填充完毕后解析出P1,剩余的数据待待60字节接收完毕后解析P2包

粘包拆包常见的解决方案

对于粘包和拆包问题,常见的解决方案有四种:

  • 发送端将每个包都封装成固定的长度,比如512字节大小。如果不足512字节可通过补0或空等进行填充到指定长度;
  • 发送端在每个包的末尾使用固定的分隔符,例如\r\n。如果发生拆包需等待多个包发送过来之后再找到其中的\r\n进行合并;例如,Redis协议,每一行的结尾都是CRLF,在碰到结尾的时候才进行转发;
  • 将消息分为头部和消息体,头部中保存整个消息的长度,只有读取到足够长度的消息之后才算是读到了一个完整的消息,例如HTTP2协议,固定先读3个字节的长度,9个字节的长度头信息;
  • 通过自定义协议进行粘包和拆包的处理。
在此的解决方案

选择了分为头部和消息体方案,头部分为8个字节,然后前3个字节表示包体的长度,单包支持长度为8-167777215也就是16m的大小,足够应对大多数情况。

网络的拓扑图

因为每个链接的处理函数均在不同的协程里,所以这里用了Sender/Receiver来同步数据。

5. 从零开始编写一个类nginx工具, 通讯协议建立, 为内网穿透做准备_数据_02

协议的分类

协议相关的类均在prot目录下面,统一对外的为枚举ProtFrame,类的定义如下

pub enum ProtFrame {
    /// 收到新的Socket连接
    Create(ProtCreate),
    /// 收到旧的Socket连接关闭
    Close(ProtClose),
    /// 收到Socket的相关数据
    Data(ProtData),
}

主要涉及类的编码及解析在方法encode,parse,定义如下

/// 把字节流转化成数据对象
pub fn parse<T: Buf>(
    header: ProtFrameHeader,
    buf: T,
) -> ProxyResult<ProtFrame> {
    
}

/// 把数据对象转化成字节流
pub fn encode<B: Buf + BufMut>(
    self,
    buf: &mut B,
) -> ProxyResult<usize> {
    
}
消息的包头

任何消息优先获取包头信息,从而才能进行相应的类型解析,类为ProtFrameHeader,定义如下,总共8个字节

pub struct ProtFrameHeader {
    /// 包体的长度, 3个字节, 最大为16m
    pub length: u32,
    /// 包体的类型, 如Create, Data等
    kind: ProtKind,
    /// 包体的标识, 如是否为响应包等
    flag: ProtFlag,
    /// 3个字节, socket在内存中相应的句柄, 客户端发起为单数, 服务端发起为双数
    sock_map: u32,
}
消息类型的定义

暂时目前定义三种类型,Create, Close, Data

  • Socket创建,类为ProtCreate
/// 新的Socket连接请求, 
/// 接收方创建一个虚拟链接来对应该Socket的读取写入
#[derive(Debug)]
pub struct ProtCreate {
    sock_map: u32,
    mode: u8,
    domain: Option<String>,
}
  • Socket关闭,类为ProtClose
/// 旧的Socket连接关闭, 接收到则关闭掉当前的连接
#[derive(Debug)]
pub struct ProtClose {
    sock_map: u32,
}
  • Socket数据包,类为ProtData
/// Socket的数据消息包
#[derive(Debug)]
pub struct ProtData {
    sock_map: u32,
    data: Binary,
}
一个数据包的自白

我是一段数据,我要去找服务器获得详细的数据

首先我得和服务器先能沟通上,建立一条可以通讯的线

5. 从零开始编写一个类nginx工具, 通讯协议建立, 为内网穿透做准备_服务端_03

此时我已经和服务端构建起了一条通讯渠道,接下来我要和他发送数据了

5. 从零开始编写一个类nginx工具, 通讯协议建立, 为内网穿透做准备_服务端_04

至此一条我与服务端已经可以说悄悄话啦。

内网穿透

内网穿秀本质上从中心服务端反向交由中心客户端构建起一条通讯渠道,如今数据协议已经建立,可由服务端推送数据到客户端进行处理,后续实现请看下篇

标签:字节,pub,nginx,从零开始,u32,长度,内网,服务端,Socket
From: https://blog.51cto.com/u_16321542/8072502

相关文章

  • 从零开始:开发直播商城APP的技术指南
    时下,直播商城APP已经成了线上购物、电子商务的核心组成,本文将为您提供一个全面的技术指南,帮助您从零开始开发一个直播商城APP。我们将涵盖所有关键方面,包括技术堆栈、功能模块、用户体验和安全性。第一部分:技术堆栈的选择1.移动平台:您可以选择iOS和Android平台开发应用,使用Swift或O......
  • LVS、Nginx、HAproxy区别与选择
    LVS:是LinuxVirtualServer的缩写,是一种基于Linux内核实现的高可用性、高性能的负载均衡技术 ;是基于四层的转发;Nginx:既是WEB服务器,缓存服务器,又是反向代理服务器,可以做七层的转发HAproxy:是基于四层和七层的转发,是专业的代理服务器;区别:LVS由于是基于四层的转发所以只能做端口......
  • Nginx安装
    Nginx安装安装必须依赖yum-yinstallmakezlibzlib-develgcc-c++libtoolopensslopenssl-develPCRE安装下载依赖文件下载PCRE安装包,下载地址:http://downloads.sourceforge.net/project/pcre/pcre/8.45/pcre-8.45.tar.gz解压文件[root@ebs-135816opt]#tar-zxvfpcre-8.......
  • [运维笔记]内网服务器或设备宕机了怎么及时收到通知并处理
    前言此前公司内网的一台服务器运行着六七个各种各样的后台任务,还跑着几个客户端。之后有一天晚上,公司里断电了,服务器也就停了,因为不是关键业务,所以之后几天谁也没发现,直到一周后才发现服务器没在处理。那怎么在服务器宕机时及时知道呢目前的简单办法:无非在服务器上跑个定时任......
  • CentOS7安装Nginx并添加成服务【转】
    当我们使用Nginx作为Web服务器时,将其添加为系统服务可以更方便地管理它的启动和停止。下面是CentOS7将Nginx添加系统服务的方法步骤:创建nginx服务配置文件首先,创建一个nginx服务配置文件,并将以下内容复制到文件中:[Unit]Description=TheNGINXHTTPandreverseprox......
  • 19. 从零开始编写一个类nginx工具, 配置数据的热更新原理及实现
    wmproxywmproxy是由Rust编写,已实现http/https代理,socks5代理,反向代理,静态文件服务器,内网穿透,配置热更新等,后续将实现websocket代理等,同时会将实现过程分享出来,感兴趣的可以一起造个轮子法项目地址gite:https://gitee.com/tickbh/wmproxygithub:https://github.com/tickbh......
  • CentOS搭建内网KMS服务器
    1.yum换源[root@cwc~]#cd/etc/yum.repos.d/[[email protected]]#mkdirback[[email protected]]#mvCentOS-Linux-*back/[[email protected]]#wget-O/etc/yum.repos.d/CentOS-Linux-BaseOS.repohttps://mirrors.aliyun.com/repo/Centos-8.repo[root@cwc......
  • window_devtunnels内网穿透
    1.安装window安装wingetinstallMicrosoft.devtunnel通过winget安装Invoke-WebRequest-Urihttps://aka.ms/TunnelsCliDownload/win-x64-OutFiledevtunnel.exe,.\devtunnel.exe-h通过powershell安装Ubuntu安装curl-sLhttps://aka.ms/DevTunnelCliInstall|......
  • 干货!分享Nginx搭建web测试报告服务器的落地方案
    Nginx搭建web测试报告服务器的实现思路有这样一个需求:把自动化测试过程中生成的html测试报告能够通过浏览器直接访问查看!实现思路很简单,就是部署一个web服务器,然后把测试报告部署到web服务器的指定目录即可,然后通过http://ip:port/path/报告名称.html的形式进行访问。我们通过ngin......
  • 从零开始:开发知识付费小程序的入门指南
    当下,知识付费小程序成为了一个独具潜力的领域。本篇文章将为您提供一份从零开始的知识付费小程序开发入门指南,让您能够进入这个领域并开始赚取您的专业知识。第一步:什么是知识付费小程序?知识付费小程序是一种基于微信小程序平台的应用,允许用户购买和访问特定领域的知识内容,如在线课......