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

Golang 的 Websocket 教程

toyiye 2024-06-21 12:41 9 浏览 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 连接发送消息:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Go WebSocket Tutorial</title>
  </head>
  <body>
    <h2>Hello World</h2>

    <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>
  </body>
</html>

如果我们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 的一些主要好处!

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码