c#手写web内网网站映射,穿透服务器(一)

本人一直做java方面开发已有六年,最近闲来无事捡起以前的c#知识写了个web网站内网映射软件。
一 、首先准备工作:
1、了解http通信协议,http/1.0及http/1.1
主要了解请求头,请求体,返回头,返回体。
不同协议的通信区别
2、了解socket 通信协议,iocp框架。
关于iocp可以在https://docs.microsoft.com/zh-cn/dotnet/api/system.net.sockets.socketasynceventargs?redirectedfrom=MSDN&view=netframework-4.7.2
去学习,当然本文中的服务端并不是以此实现。
3、熟悉通信过程中的封包,粘包,解包操作
xxxxyyyyyyyyyyyyyyyyyyyyy
封包的意思就是4个字节32位来表示本次包体数据长度。
二、实现思路
1、既然是要内网通信,首先我们能够想到内网的数据肯定要通过通信软件进行转发,所以呐我们需要开发一个通信的客户端负责接收服务端发来的请求及向内网网站应用发起请求,获取返回结果并将数据发回服务端,再由服务端返回给请求方。

图画图随便画的有点丑,将就看吧,能明白意思就行。
在这里插入图片描述
2、我们看整个过程其实数据的传输步骤还挺多的,的确要实现此功能基础架构免不了这样,而我们要实现高并发及提高传输效率就需要实现多进程,拿一个wener服务端举例,一个TcpServer (后面简称Worker)负责监听并接收请求,而我们根据CPU的数量启动其它几个在wener客户端通信的进程,Worker根据hash算法将请求分发到不同子进程,子进程根据http请求头中的Host属性决定将数据发到某个wener客户端实现数据交互。子进程和wener客户端之间的数据是进行了封包及压缩。
3、子进程在通信过程会有一个参数告诉wener客户端数据是否发送完成,比如一个Get请求头:
GET /url HTTP/1.1\r\n
Accept-Language: zh-cn,zh;q=0.5\r\n
Accept-Charset: GB2312,utf-8;q=0.7,;q=0.7\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,
/;q=0.8\r\n
Accept-Encoding: gzip, deflate\r\n
User-Agent: Mozilla/5.0 (compatible; 域名)\r\n
Host: 域名\r\n
Connection: Keep-Alive\r\n\r\n
当我们接收到数据并且以\r\n\r\n 结束就是所有的请求头参数结束。而每一个请求参数之间是以\r\n来拆分的。
get请求不包含Content-Length属性,所以我们断定该请求数据接收完成。
一个Post请求头
POST /url HTTP/1.1\r\n
Accept-Language: zh-cn,zh;q=0.5\r\n
Accept-Charset: GB2312,utf-8;q=0.7,
;q=0.7\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8\r\n
Accept-Encoding: gzip, deflate\r\n
Content-Length: 5\r\n
User-Agent: Mozilla/5.0 (compatible; 域名)\r\n
Host: 域名\r\n
Connection: Keep-Alive\r\n\r\n
11111
我们拿到请求头后发现包含Content-Length因此我们接收到 Content-Length指定的包体部分后告诉wener客户端数据已发送完成。
至于为什么要告诉wener客户端数据发送完成我们后面再说。
这里就不对http 返回报文作解释了。
不过你需要明白的是现在虽然http/1.1保持长连接,但肯定是一个请求完成后,未关闭的连接才会再次发起请求,也就是一个通道里面不会同时存在两个请求头(用户对Worker之间的通信)。
4、这里还是简单提一下返回报文,万一有同学有兴趣想自己实现呐。
http/1.0的返回报文
返回头里面会有一个Connection:close 并且一个请求完成是以服务端关闭连接结束。
对于报文里面的Content-Length: 5\r\n 主要是告诉客户端本次返回的body数据长度是多少,注意此长度是不包含返回头。
在这里插入图片描述
对于http/1.1协议会有另外一个参数来表示一些不固定长度的返回:
Transfer-Encoding:chuncked
表示数据是分块传输像一些动态页面就会使用此参数进行返回
如: (这是网上复制的)
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

25
This is the data in the first chunk

1A
and this is the second one
0
一个十六进制表示接下来的数据块长度
最终以0\r\n\r\n结束表示已经没有数据,所以我们完全可以通过是否最后5个字节数据是0\r\n\r\n
5、好了原理已经说得差不多了,在这篇就不具体的贴什么代码之类我估计看的人也恼火就直接上客户端的下载地址。
https://download.csdn.net/download/went361346846/10935387

6、对这方面有兴趣或者想要沟通及学习的可以加群398365278(wener)

三、安全性的考虑
可以从这几方面去考虑
1、wener服务端与wener客户端之间的通信采用加密技术。
2、Worker设置请求门槛,如:连接建立后如果一定时间未接收到请求头直接关闭连接。
3、设置连接的keep-alive时间。
4、控制超时时间,如:请求消息发送完成后,一定时间没有收到服务器回复直接关闭连接。
5、控制同一IP在一秒内的请求数量
其它请大家建议
好了,快过年了祝大家新快乐,有时间再更新。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值