本文发表于入职啦(公众号: ruzhila) 大家可以访问入职啦学习更多的编程实战。
🎉 用Go实现Websocket转TCP代理,浏览器可以访问TCP Socket,网络编程入门 实用项目 👏 🎉
项目地址
代码已经开源, websockify-go 👏 欢迎Star
代码运行效果:
所有的项目都在github上开源:100-line-code 欢迎Star 👏
用100行代码的不同语言(Java、Python、Go、Javascript、Rust)实现项目,通过讲解项目的实现,帮助大家学习编程
我们会定期在群里分享最新的项目实战代码,包括不同语言的实现
老师还会详细讲解代码优化的思路,扫码加入实战群:
为什么需要Websocket转TCP
Websocket是一种全双工通信协议,可以在浏览器和服务器之间建立持久连接,用于实时通信。但是Websocket只支持文本和二进制数据,无法直接访问TCP Socket。 如果要在网页上访问TCP Socket,就需要一个代理服务器,将Websocket请求转发到TCP Socket, 这就是Websocket转TCP代理:
Websocket <----> Websocket转TCP代理 <----> TCP Socket
典型的场景:
- 在浏览器上访问VNC远程桌面
- 在浏览器上访问SSH终端
- 在浏览器上访问数据库管理工具
- 在浏览器上访问自定义TCP服务, 比如游戏服务器或者IM服务器
novnc/websockify是一个非常流行的Websocket转TCP代理,但是它是用Python实现的,性能不够好,代码也很复杂
用Go实现一个Websocket转TCP代理,性能更好,更稳定
Go实现Websocket转TCP代理
Go特别适合网络编程,标准库提供了丰富的网络库,不仅性能好,而且代码简洁,只需要一个可执行文件就可以运行,不需要依赖其他库 这次要通过100行代码实现一个Websocket转TCP代理:
- 要支持SSL
- 要支持自定义URL路径
- 要支持自定义目标地址
- 完整的单元测试和标准的服务程序架构
代码
代码解析
代码结构
- cmd/main.go 是程序的入口,解析命令行参数,启动服务
- websockify.go 是Websocket转TCP代理的核心代码
- websockify_test.go 是单元测试代码
- Dockerfile 是构建Docker镜像的文件,方便部署可以直接上生产系统
启动一个HTTP服务器
- 82行: 监听一个HTTP端口
- 89-95行: 如果是443并且有SSL证书,就启动一个HTTPS服务器
- 86行: 利用标准库创建一个能自定义处理的HTTP Server
处理Websocket请求
采用了gorilla/websocket库来处理Websocket请求,这个库是Go语言中最流行的Websocket库
所有的业务逻辑都在ServeHTTP函数:
- 31行: 升级HTTP连接为Websocket连接, Websocket协议是基于GET这个HTTP请求升级为Websocket协议
- 36行: 利用defer关键字,当链接断开的时候,关闭TCP连接,确保不会泄露资源
- 44-59行: 读取Websocket数据,转发到TCP Socket
- 60-73行: 读取TCP Socket数据,转发到Websocket
一个链接启动了两个协程
其实从ServerHTTP这个函数开始,系统库就为每个请求创建了一个协程,这个协程负责处理这个请求
在这个函数里面又启动了两个协程:
- 一个负责读取Websocket数据
- 一个负责读取TCP Socket数据
这样就实现了一个链接同时处理两个方向的数据流
- 43和75行 创建了能接受err的channel,当处理数据从协程出现错误的时候,就会发送一个错误到这个channel,然后当前的主协程就会退出关闭链接
单元测试
golang的单元测试非常的方便,只需要在文件名后面加上_test.go,然后在函数名前面加上Test就可以了
单元测试的逻辑:
- 2-28行 创建一个测试用的TCP服务器,写了一个Echo服务器,就是把接收到的数据原样返回
- 31-41行 创建一个Websockify代理服务器
- 43-63行 启动一个Websocket客户端测试链接是否能正常工作
标准的服务器程序架构
这个项目提供了Dockerfile,现在Docker是最主要的线上程序交付方式,强烈建议用Docker部署服务 基于flag这个库,来处理命令行参数,这是Go语言标准库提供的命令行参数解析库
程序能支持的命令行参数来控制服务的启动
总结
通过Websockify这个项目,学习了Go语言的网络编程,Websocket是一个非常重要的协议,可以用于实时通信,实现一个Websockify的转发代理,对于内部项目的开发非常有用
Docker也是非常重要的技术,提供了Dockerfile,可以直接部署到生产环境
过去的演示项目都没提供单元测试,提供了一个非常实用的单元测试流程,大家可以参考即便是复杂的流程也是可以通过单元测试来验证的
交流
我们构建了一个100行代码项目的实战群,大家可以扫码加入,一起学习编程
也可以访问入职啦学习更多的编程实战
所有的代码都在github上开源:100-line-code 欢迎Star 👏