百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

Golang 的 Websocket 教程

yuyutoo 2025-03-08 01:58 11 浏览 0 评论

嗨,开发人员!在本教程中,我们将研究如何在我们自己的基于 Go 的程序中使用 WebSockets 来做一些很酷的实时事情。

在本教程结束时,我们应该已经涵盖了以下内容:

  • 什么是 WebSocket
  • 我们如何在 Go 中构建简单的 WebSocket 应用程序

出于本教程的目的,我们将使用该gorilla/websocket软件包,因为我曾在一些生产应用程序中亲自使用它并取得了巨大的成功。

WebSockets - 它们是什么?

因此,我在许多不同的教程中多次介绍了这一点,但始终值得一提的是我们为什么使用 WebSocket 以及它们与传统HTTP请求有何不同。

WebSockets 是升级后的 HTTP 连接,在连接被客户端或服务器终止之前一直存在。正是通过这个 WebSocket 连接,我们可以执行双工通信,这是一种非常奇特的方式,可以说我们可以使用这个单一连接从我们的客户端与服务器进行通信。

WebSockets 的真正美妙之处在于它们总共使用了 1 个 TCP 连接,并且所有通信都是通过这个单一的长寿命 TCP 连接完成的。这大大减少了使用 WebSockets 构建实时应用程序所需的网络开销,因为不需要对 HTTP 端点进行持续轮询。

一个简单的例子

让我们从一个非常简单的 Go 程序开始,一旦我们可以运行它,我们就可以在它之上构建并开始构建一些简单的 WebSocket 端点。

我们需要首先go modules通过调用来初始化我们的项目以使用:

$ go mod init github.com/elliotforbes/go-websocket-tutorial

这个命令应该go.mod在我们的当前目录中创建一个文件。

完成后,我们可以继续定义我们的main.go文件,我们将在其中进行大部分编码:

main.go

package main

import "fmt"

func main() {
    fmt.Println("Hello World")
}

让我们通过打开终端、导航到项目目录然后调用go run main.go. 我们应该看到它Hello World在我们的终端中成功输出。

一个简单的 HTTP 端点

我们将从构建一个简单的 HTTP 服务器开始,Hello World只要我们在 port 上点击它就会返回8080。我们还将定义一个简单的 HTTP 端点,它将作为我们将要创建的 WebSocket 端点的基础:

package main

import (
    "fmt"
    "log"
    "net/http"
)

func homePage(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Home Page")
}

func wsEndpoint(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello World")
}

func setupRoutes() {
    http.HandleFunc("/", homePage)
    http.HandleFunc("/ws", wsEndpoint)
}

func main() {
    fmt.Println("Hello World")
    setupRoutes()
    log.Fatal(http.ListenAndServe(":8080", nil))
}

太棒了,当我们尝试运行它时,go run main.go我们应该看到它成功地启动了我们新定义的 HTTP 服务器,http://localhost:8080随后我们应该能够在我们的浏览器中点击/和/ws路由。

升级 HTTP 连接

为了创建 WebSocket 端点,我们实际上需要将传入连接从标准 HTTP 端点升级为持久的 WebSocket 连接。为了做到这一点,我们将使用非常酷的gorilla/websocket软件包中的一些功能!

定义我们的升级程序

我们要做的第一件事是定义一个websocker.Upgrader结构。这将保存诸如 WebSocket 连接的读取和写入缓冲区大小之类的信息:

// We'll need to define an Upgrader
// this will require a Read and Write buffer size
var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
}

检查传入来源

我们要添加到现有wsEndpoint函数的下一件事是调用 upgrader.CheckOrigin. 这将确定是否允许来自不同域的传入请求连接,如果不是,它们将被CORS错误击中。

func wsEndpoint(w http.ResponseWriter, r *http.Request) {
    // remove the previous fmt statement
    // fmt.Fprintf(w, "Hello World")
    upgrader.CheckOrigin = func(r *http.Request) bool { return true }

}

目前,我们保持它非常简单,无论哪个主机尝试连接到我们的端点,都简单地返回 true。

升级我们的连接

我们现在可以开始尝试使用接收upgrader.Upgrade()响应写入器和指向 HTTP 请求的指针的函数来升级传入的 HTTP 连接 ,并返回一个指向 WebSocket 连接的指针,或者如果升级失败则返回错误。

func wsEndpoint(w http.ResponseWriter, r *http.Request) {
    upgrader.CheckOrigin = func(r *http.Request) bool { return true }

    // upgrade this connection to a WebSocket
    // connection
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println(err)
    }

}

持续聆听该连接

接下来,我们将要实现一个函数,该函数将持续侦听通过该 WebSocket 连接发送的任何传入消息。我们reader()现在将调用它,它将接收一个指向我们从调用中收到的 WebSocket 连接的指针upgrader.Upgrade:

// define a reader which will listen for
// new messages being sent to our WebSocket
// endpoint
func reader(conn *websocket.Conn) {
    for {
    // read in a message
        messageType, p, err := conn.ReadMessage()
        if err != nil {
            log.Println(err)
            return
        }
    // print out that message for clarity
        fmt.Println(string(p))

        if err := conn.WriteMessage(messageType, p); err != nil {
            log.Println(err)
            return
        }

    }
}

有了这个定义,我们就可以将它添加到我们的wsEndpoint函数中,如下所示:

func wsEndpoint(w http.ResponseWriter, r *http.Request) {
    upgrader.CheckOrigin = func(r *http.Request) bool { return true }

    // upgrade this connection to a WebSocket
    // connection
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println(err)
    }
    // helpful log statement to show connections
    log.Println("Client Connected")

    reader(ws)
}

有了所有这些,我们现在应该能够像这样运行我们的新 WebSocket 服务器:

$ go run main.go
Hello World

太棒了,一切似乎都奏效了!

回信给我们的客户

我之前提到过,WebSockets 允许双工通信,即跨同一个 TCP 连接的来回通信。为了从我们的 Go 应用程序向任何连接的 WebSocket 客户端发送消息,我们可以ws.WriteMessage() 像这样使用该函数:

func wsEndpoint(w http.ResponseWriter, r *http.Request) {
    upgrader.CheckOrigin = func(r *http.Request) bool { return true }

    // upgrade this connection to a WebSocket
    // connection
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println(err)
    }

    log.Println("Client Connected")
    err = ws.WriteMessage(1, []byte("Hi Client!"))
    if err != nil {
        log.Println(err)
    }
    // listen indefinitely for new messages coming
    // through on our WebSocket connection
    reader(ws)
}

这个添加意味着任何连接到我们的 WebSocket 服务器的客户端都会收到一条好Hi Client!消息!

测试一切都与客户一起工作

最后一步是通过创建客户端并尝试连接到我们的新 WebSocket 端点来测试是否一切正常。为此,我们将创建一个非常简单的原生 JavaScript 应用程序,它将连接ws://localhost:8080/ws并尝试通过这个新的 WebSocket 连接发送消息:



  
    
    
    
    Go WebSocket Tutorial
  
  
    

Hello World

<script> let socket = new WebSocket("ws://127.0.0.1:8080/ws"); console.log("Attempting Connection..."); socket.onopen = () => { console.log("Successfully Connected"); socket.send("Hi From the Client!") }; socket.onclose = event => { console.log("Socket Closed Connection: ", event); socket.send("Client Closed!") }; socket.onerror = error => { console.log("Socket Error: ", error); }; </script>

如果我们index.html在浏览器中打开此页面,我们应该在控制台中看到它已经能够成功连接!

我们还应该在我们的服务器日志中看到客户端已成功连接以及一条Hi From The Client!消息!

我们现在已经实现了全双工通信!

Docker 化我们的应用程序

我在其他许多教程中都谈到了 Docker 的好处,但本质上,它允许我们定义应用程序成功运行所需的确切环境。这意味着您应该能够在 10 年内运行本教程,并且它应该仍然可以完美运行。

FROM golang:1.11.1-alpine3.8
RUN mkdir /app
ADD . /app/
WORKDIR /app
RUN go mod download
RUN go build -o main ./...
CMD ["/app/main"]

现在我们已经Dockerfile为我们的应用程序定义了这个,让我们image 使用docker build命令创建,然后让我们尝试在 Docker 中运行这个 Go WebSocket 应用程序container。

$ docker build -t go-websocket-tutorial .
$ docker run -it -p 8080:8080 go-websocket-tutorial

如果一切顺利,我们应该能够看到我们的应用程序在映射到本地机器端口的 docker 容器中启动并运行8080。如果我们http://localhost:8080在浏览器中打开 ,我们应该会看到我们的应用程序返回home page。

结论

在本教程中,我们设法介绍了 WebSockets 的一些基础知识,以及如何在 Go 中构建一个简单的基于 WebSocket 的应用程序!

因此,希望您喜欢本教程并发现它很有用!我希望这突出了在您自己的 Go 应用程序中使用 WebSockets 的一些主要好处!

相关推荐

《保卫萝卜2》安卓版大更新 壕礼助阵世界杯

《保卫萝卜2:极地冒险》本周不仅迎来了安卓版本的重大更新,同时将于7月4日本周五,带来“保卫萝卜2”安卓版本世界杯主题活动的火热开启,游戏更新与活动两不误。一定有玩家会问,激萌塔防到底进行了哪些更新?...

儿童手工折纸:胡萝卜,和孩子一起边玩边学carrot

1、准备两张正方形纸,一橙一绿,对折出折痕。2、橙色沿其中一条对角线如图折两三角形。3、把上面三角折平,如图。4、绿色纸折成三角形。5、再折成更小的三角形。6、再折三分之一如图。7、打开折纸,压平中间...

《饥荒》食物代码有哪些(饥荒最新版代码总汇食物篇)

饥荒游戏中,玩家们需要获取各种素材与食物,进行生存。玩家们在游戏中,进入游戏后按“~”键调出控制台使用代码,可以直接获得素材。比如胡萝卜的代码是carrot,玉米的代码是corn,南瓜的代码是pump...

Skyscanner:帮你找到最便宜机票 订票不求人

你喜欢旅行吗?在合适的时间、合适的目的地,来一场说走就走的旅行?机票就是关键!Skyscanner这款免费的手机应用,在几秒钟内比较全球600多家航空公司的航班安排、价格和时刻表,帮你节省金钱和时间。...

小猪佩奇第二季50(小猪佩奇第二季英文版免费观看)

Sleepover过夜Itisnighttime.现在是晚上。...

我在民政局工作的那些事儿(二)(我在民政局上班)

时间到了1997年的秋天,经过一年多的学习和实践,我在处理结婚和离婚的事情更加的娴熟,也获得了领导的器重,所以我在处理平时的工作时也能得心应手。这一天我正在离婚处和同事闲聊,因为离婚处几天也遇不到人,...

夏天来了就你还没瘦?教你不节食13天瘦10斤的哥本哈根减肥法……

好看的人都关注江苏气象啦夏天很快就要来了你是否和苏苏一样身上的肉肉还没做好准备?真是一个悲伤的故事……下面这个哥本哈根减肥法苏苏的同事亲测有效不节食不运动不反弹大家快来一起试试看吧~DAY1...

Pursuing global modernization for peaceful development, mutually beneficial cooperation, prosperity for all

AlocalworkeroperatesequipmentintheChina-EgyptTEDASuezEconomicandTradeCooperationZonei...

Centuries-old tea road regains glory as Belt and Road cooperation deepens

FUZHOU/ST.PETERSBURG,Oct.2(Xinhua)--NestledinthepicturesqueWuyiMountainsinsoutheastChi...

15 THE NUTCRACKERS OF NUTCRACKER LODGE (CONTINUED)胡桃夹子小屋里的胡桃夹子(续篇)

...

AI模型部署:Triton Inference Server模型部署框架简介和快速实践

关键词:...

Ftrace function graph简介(flat function)

引言由于android开发的需要与systrace的普及,现在大家在进行性能与功耗分析时候,经常会用到systrace跟pefetto.而systrace就是基于内核的eventtracing来实...

JAVA历史版本(java各版本)

JAVA发展1.1996年1月23日JDK1.0Java虚拟机SunClassicVM,Applet,AWT2.1997年2月19日JDK1.1JAR文件格式,JDBC,JavaBea...

java 进化史1(java的进阶之路)

java从1996年1月第一个版本诞生,到2022年3月最新的java18,已经经历了27年,整整18个大的版本。很久之前有人就说java要被淘汰,但是java活到现在依然坚挺,不知道java还能活...

学习java第二天(java学完后能做什么)

#java知识#...

取消回复欢迎 发表评论: