Golang 实现 WebSockets 之创建 WebSockets


Posted in Golang onApril 24, 2022

前言

上一篇文章 Golang 实现WebSockets中我们先介绍了什么是 WebSockets 协议。本篇文章将来介绍如何利用 Go 来实现一个 WebSockets。要基于 net/http 库编写一个简单的 WebSocket 响应服务器,我们需要:

  • 建立握手
  • 从客户端接收数据帧
  • 向客户端发送数据帧
  • 关闭握手

WebSockets 无需客户端事先请求即可从服务器传输数据,允许来回传递消息并保持连接打开,直到客户端或服务器终止它。因此,可以在客户端和服务器之间进行双向实时数据传输。 WebSocket 通信通常通过 TCP 端口号 443 完成。

WebSocket 协议规范定义了两种 URI 方案:

  • WebSocket (ws):用于非加密连接
  • WebSocket Secure (wss):用于加密连接

建立 HTTP 服务器

WebSockets 建立在 HTTP 之上,所以首先,我们将设置一个基本的 HTTP 服务器,它可以接受客户端连接并提供消息。将以下代码添加到我们的 ​​server.go​​ 文件中:

package main

import (
"fmt"
"net/http"
)

func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to the server!\n")
})

http.ListenAndServe(":8080", nil)
}

通过运行 ​​go run server.go​​​ 启动服务器。当您访问 ​​localhost:8080​​ 时,您应该会看到以下输出:
 

Welcome to the server!

Golang 实现 WebSockets 之创建 WebSockets

发起握手

由于开销较小,WebSocket 可以在 Web 服务器和 Web 浏览器或客户端应用程序之间实现实时通信和快速数据传输。 WebSocket 通信发起一个握手,它使用 HTTP Upgrade() 标头从 HTTP 协议更改为 WebSocket 协议。

要建立 WebSocket 连接,需要在客户端和服务器之间进行一次握手。握手使用 Upgrade() 方法将 HTTP 服务器连接升级到 WebSocket 协议。一旦服务器停止,我们还将使用 defer 关闭连接。

现在,我们修改 ​​server.go​​ 文件,建立一个 WebSocket 握手:

首先,我们需要获取​​gorilla/websocket​​ 库:

$ go get github.com/gorilla/websocket

定义一个 upgrader 结构,用来保存 WebSocket 连接的读取和写入缓冲区大小等信息:

var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}

然后更改​​server.go​​ 代码:

package main

import (
"fmt"
"net/http"

"github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}

func main() {
http.HandleFunc("/echo", func(w http.ResponseWriter, r *http.Request) {
conn, _ := upgrader.Upgrade(w, r, nil) // error ignored for sake of simplicity

for {
// Read message from browser
msgType, msg, err := conn.ReadMessage()
if err != nil {
return
}

// Print the message to the console
fmt.Printf("%s sent: %s\n", conn.RemoteAddr(), string(msg))

// Write message back to browser
if err = conn.WriteMessage(msgType, msg); err != nil {
return
}
}
})

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "websockets.html")
})

http.ListenAndServe(":8080", nil)
}

新建一个​​websockets.html​​ 文件,写入如下代码:

<!-- websockets.html -->
<input id="input" type="text" />
<button onclick="send()">Send</button>
<pre id="output"></pre>
<script>
var input = document.getElementById("input");
var output = document.getElementById("output");
var socket = new WebSocket("ws://localhost:8080/echo");

socket.onopen = function () {
output.innerHTML += "Status: Connected\n";
};

socket.onmessage = function (e) {
output.innerHTML += "Server: " + e.data + "\n";
};

function send() {
socket.send(input.value);
input.value = "";
}
</script>

运行​​go run server.go​​ 文件

打开浏览器,输入​​http://localhost:8080/​​ ,然后就能看到如下界面:

Golang 实现 WebSockets 之创建 WebSockets

当我们向服务器输入hello 后,然后单击​​Send​​ 按钮。

界面如下:

Golang 实现 WebSockets 之创建 WebSockets

回到服务器终端也能看到如下信息:

$ go run server.go
[::1]:58036 sent: Hello

至此,一个简单的 WebSockets 就完全实现了。接下来,我们看一下 WebSockets 有哪些实际运用。

WebSockets 的用例

因为 WebSockets 的主要目的是支持全双工或双向通信。除了提供实时更新外,WebSockets 还包括一个可以支持多个打开的 WebSocket 连接的轻量级服务器。与大多数其他方法相比,WebSockets 可以在更长的时间内维持客户端和服务器之间的连接。

目前,WebSockets 为 Android、iOS、Web 和桌面应用程序提供跨平台支持,WebSockets 常用于以下类型的应用程序:

  • 实时消息
  • 多人游戏
  • 实时比分提要
  • 协作编辑工具
  • 实时位置和方向应用
  • 使用 WebRTC 进行音频和视频聊天

总结

在本文中,我们探索了 WebSockets,并简要介绍了它们的工作原理,并仔细研究了全双工通信。为了了解 WebSocket 在 Go 中的工作原理,我们构建了一个简单的待办事项应用程序,该应用程序具有添加和删除任务的功能。最后,我们查看了使 WebSockets 有用和通用的几个附加特性,并回顾了 WebSockets 的一些实际应用。在 Go 中使用 WebSockets 相当简单明了,但这种组合会对应用程序的性能产生显着影响。


Tags in this post...

Golang 相关文章推荐
Go语言 go程释放操作(退出/销毁)
Apr 30 Golang
关于golang高并发的实现与注意事项说明
May 08 Golang
golang 实现并发求和
May 08 Golang
浅谈Golang 切片(slice)扩容机制的原理
Jun 09 Golang
go语言使用Casbin实现角色的权限控制
Jun 26 Golang
Go语言并发编程 sync.Once
Oct 16 Golang
Go归并排序算法的实现方法
Apr 06 Golang
GO语言异常处理分析 err接口及defer延迟
Apr 14 Golang
Golang 字符串的常见操作
Apr 19 Golang
Golang ort 中的sortInts 方法
Apr 24 Golang
Go微服务项目配置文件的定义和读取示例详解
Jun 21 Golang
Go语言测试库testify使用学习
Jul 23 Golang
Golang 实现WebSockets
Golang ort 中的sortInts 方法
Apr 24 #Golang
Golang 切片(Slice)实现增删改查
Apr 22 #Golang
Golang 结构体数据集合
Apr 22 #Golang
Golang map映射的用法
Apr 22 #Golang
Golang bufio详细讲解
Apr 21 #Golang
Go获取两个时区的时间差
Apr 20 #Golang
You might like
php empty函数 使用说明
2009/08/10 PHP
php foreach 使用&amp;(与运算符)引用赋值要注意的问题
2010/02/16 PHP
使用PHP求两个文件的相对路径
2013/06/20 PHP
php上传文件中文文件名乱码的解决方法
2013/11/01 PHP
php实现微信支付之企业付款
2018/05/30 PHP
PHP模型Model类封装数据库操作示例
2019/03/14 PHP
添加到收藏夹代码(兼容几乎所有的浏览器)
2007/01/09 Javascript
Jquery知识点二 jquery下对数组的操作
2011/01/15 Javascript
jquery 提示信息显示后自动消失的具体实现
2013/12/18 Javascript
json中换行符的处理方法示例介绍
2014/06/10 Javascript
排序算法的javascript实现与讲解(99js手记)
2014/09/28 Javascript
JS实现的仿QQ空间图片弹出效果代码
2016/02/23 Javascript
Bootstarp风格的toggle效果分享
2016/02/23 Javascript
js+css3实现旋转效果
2017/01/20 Javascript
JS中使用gulp实现压缩文件及浏览器热加载功能
2017/07/12 Javascript
vue中keep-alive的用法及问题描述
2018/05/15 Javascript
小程序自定义组件实现城市选择功能
2018/07/18 Javascript
iview同时验证多个表单问题总结
2018/09/29 Javascript
Vue3.0 响应式系统源码逐行分析讲解
2019/10/14 Javascript
vue form表单post请求结合Servlet实现文件上传功能
2021/01/22 Vue.js
[01:33]DOTA2上海特级锦标赛 LIQUID战队完整宣传片
2016/03/16 DOTA
分析在Python中何种情况下需要使用断言
2015/04/01 Python
浅谈插入排序算法在Python程序中的实现及简单改进
2016/05/04 Python
使用Python脚本实现批量网站存活检测遇到问题及解决方法
2016/10/11 Python
Python 批量合并多个txt文件的实例讲解
2018/05/08 Python
Python实现九宫格式的朋友圈功能内附“马云”朋友圈
2019/05/07 Python
python 对字典按照value进行排序的方法
2019/05/09 Python
Pycharm及python安装详细步骤及PyCharm配置整理(推荐)
2020/07/31 Python
Python求解排列中的逆序数个数实例
2020/05/03 Python
Html5如何唤起百度地图App的方法
2019/01/27 HTML / CSS
意大利珠宝店:Luxury Zone
2019/01/05 全球购物
商场促销活动策划方案
2014/08/18 职场文书
小学国旗下的演讲稿
2014/08/28 职场文书
三年级上册科学教学计划
2015/01/21 职场文书
2015年暑期实践报告范文
2015/07/13 职场文书
golang 在windows中设置环境变量的操作
2021/04/29 Golang