当前位置:网站首页>[Go WebSocket] 你的第一个Go WebSocket服务: echo server
[Go WebSocket] 你的第一个Go WebSocket服务: echo server
2022-08-10 18:34:00 【51CTO】
大家好,我是公众号「线下聚会游戏」作者,开发了 《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏。其中的核心技术就是WebSocket,快来关注专栏 《Go WebSocket》,跟我一起学习吧!
背景
上篇文章: 《为什么我选用Go重构Python版本的WebSocket服务?》,介绍了我的目标。
从这篇文章开始,我们进入实战,正式介绍Go WebSocket框架。
还没学过Go,要先看什么?
建议你花1天时间,看一下Go的原理简介、基础语法。什么教程都可以,知名的教程就行。
至少要明白:各种数据类型,控制流(for、if等)写法,弄懂channel和goroutine,如何加锁。
一定要自己写写goroutine和channel试一下,了解一下基础语法。
此外,还要了解常用包的用法,包括fmt、net/http。
技术选型
面对自己不熟悉的语言和不熟悉的框架,该怎么做技术选型呢?
我告诉你个小技巧,直接在Github上搜索,看Star最多的那个仓库,就可以啦~
看吧,我们搜到了gorilla/websocket
,star数以显著差异甩开了后面几名。这就没有什么好纠结的了,果断使用它。
新建项目
在使用GoLand时,新建Go Project会有2个选项:
我们选用第一个即可。
如果你没有GoLand,也可以手动创建文件夹,在里面新建文件go.mod
(我是使用的目前最新稳定版1.18)
安装依赖
拷贝echo代码
把gorilla/websocket
的官方demo拷贝过来即可,我们慢慢分析:
只需要拷贝这一个文件,命名为server.go即可。
先尝试运行
然后浏览器打开 localhost:8080就可以了~
- 点击「Open」建立WebSocket连接
- 编辑好文本,按Send发送一个消息给服务器
- 服务器立马回复一个一模一样的消息,这就是echo
- 点击「Close」关闭连接,之后无法Send
你的所有操作都会记录在页面上:
当然,也可以打开开发者工具,查看WebSocket连接,就像你查看Http请求那样。这篇文章教了你怎样使用Chrome的开发者面板抓包: 《遇到表格,手动翻页太麻烦?我教你写脚本,一页展示所有数据》。
代码解读
引入依赖
定义服务地址
这是定义了服务器启动服务的地址,flag
包用于处理命令行参数。意思是这个服务地址是可以通过命令行参数动态修改的。
比如你可以这样启动:go run server.go -addr="localhost:8888"
那么浏览器就应该打开localhost:8888
来访问。
当然如果你不需要命令后参数传入addr,完全可以删掉这行,改为:
同时,还要把main函数中,最后一行改成:(删掉了addr前面的星号)
同时,把flag
相关的行都删掉。(开头的import和main函数中的Parse)
主函数
我们先介绍一下主函数(虽然主函数定义在后面)。但是主函数有一个路由的作用,分发了请求。我们先介绍一下,方便后续理解。
我们通过net/http
提供的能力,使用ListenAndServe
启动了Http/WebSocket服务。
其中,我们注册了2个处理函数,一个是针对path为/echo
的,这是用echo函数处理。另一个是针对path为/
的,这是用home函数处理。
当你用浏览器直接访问localhost:8080
时,是用了home
函数处理,一个http请求,获得一个html文件,在浏览器展示。
当你在JS中写new WebSocket('wss://localhost:8080/echo')
时,是用了echo
函数处理,一个WebSocket连接。
我们接下来介绍这2个函数。
定义echo服务(WebSocket协议)
当客户端使用new WebSocket('ws://localhost:8080/echo')
建立时,就会开启一个goroutine,执行类似go echo(w, r)
的操作。只要这个WebSocket没有关闭,那么这个goroutine就会一直存在。
如果客户端关闭了WebSocket,或者服务端的这个goroutine执行结束了(因为有defer c.Close()
),都会导致WebSocket断掉。这是合理且正确的,不这么写会有问题。
这段echo
函数很简单,不断循环,读取消息c.ReadMessage()
,如果没消息,那么就会暂停执行,直到有了消息。有消息后,通过log
打印收到的消息,并且通过c.WriteMessage(mt, message)
输出消息给客户端。
这里mt
是消息类型Message Type,有2种:二进制消息、文本消息。
当服务器输出完毕后,又在等待客户端的输入了。
可以看到,目前是一个有序的线性服务:收一个、发一个、收一个、发一个。如果客户端同时发了100个,那么服务端也会按照这100个消息的顺序读取,并且按原先的顺序echo回去。处理完一个、才会去接收下一个。好处是保证了收发的顺序性(服务端发的顺序一定跟收的顺序一致),坏处是无法并发的读,性能有影响,如果每个处理收到消息要处理很久,后面的消息就阻塞、积压在内存中了。
下一篇我们会介绍chat server
,避免了这种问题。 敬请期待,可以先关注专栏、关注我噢~。
Html文本服务(Http协议)
这个服务比较简单,就是Html模板渲染。
注意有个模板变量:"ws://"+r.Host+"/echo"
,其实这个模板变量是不需要的。
HTML中可以直接这么写:把ws = new WebSocket("{{.}}");
改为ws = new WebSocket('ws://' + window.location.host + '/echo');
写在最后
我是HullQin,独立开发了 《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏,不收费无广告。还独立开发了 《合成大西瓜重制版》。还开发了 《Dice Crush》参加了某个游戏制作比赛。喜欢可以关注我噢~我有空了会分享做游戏的相关技术,会在这2个专栏里分享: 《教你做小游戏》、 《极致用户体验》。
本文正在参加 技术专题18期-聊聊Go语言框架。
边栏推荐
- 微服务架构-实现技术之六大基础组件:服务通信+事件驱动+负载均衡+服务路由+API网关+配置管理
- Thoughts on Technology Sharing
- 谈谈宝石方块游戏中的设计
- C#/VB.NET 将PDF转为PDF/X-1a:2001
- 【测试】黑盒测试用例设计方法
- 西安凯新(CAS:2408831-65-0)Biotin-PEG4-Acrylamide 特性
- stm32中的CAN通讯列表模式配置解析与源码
- 陕西CAS:1244028-50-9_Biotin-PEG3-SCO-PPh3 固体
- Biotin-PEG4-IC(TFP ester/amine/NHS Ester/azide)特性分享
- 【OpenCV】-物体的凸包
猜你喜欢
Consul简介和安装
工业基础类—利用xBIM提取IFC几何数据
set和map使用讲解
【HMS core】【FAQ】Analytics Kit、Push Kit典型问题合集3
多种深度模型实现手写字母MNIST的识别(CNN,RNN,DNN,逻辑回归,CRNN,LSTM/Bi-LSTM,GRU/Bi-GRU)
【HMS core】【FAQ】Account Kit、push Kit典型问题合集1
选择是公有云还或是私有云,这很重要吗?
MSE 治理中心重磅升级-流量治理、数据库治理、同 AZ 优先
FPGA:生成固化文件(将代码固化到板子上面)
【FAQ】【Push Kit】推送服务,回执配置一直报错、回执过期修改、怎么删除配置的回执
随机推荐
Major upgrade of MSE Governance Center - Traffic Governance, Database Governance, Same AZ Priority
人生苦短,开始用go
API 网关的功能
shell运算详解,看这一篇就够了!
flex&bison系列第一章:flex Hello World
请问下在datastream中用flinkcdc怎么设置jdbc的参数useSSL=false呀
多线程与高并发(五)—— 源码解析 ReentrantLock
钻石价格预测的ML全流程!从模型构建调优道部署应用!
一颗完整意义的LPWAN SOC无线通信芯片——ASR6601
RS-485多主机通信的组网方式评估
CEO对今天的CIO们真正的要求是什么?
[Image dehazing] Image dehazing based on color attenuation prior with matlab code
Qt学习第三天
800. 数组元素的目标和(双指针)
websocket校验token:使用threadlocal存放和获取当前登录用户
365天挑战LeetCode1000题——Day 053 求解方程 解析 模拟
003-序列图(一)
postgis空间数据导入及可视化
【HMS core】【FAQ】Account Kit、push Kit典型问题合集1
PG中的Index-Only Scans解密