首页 > 其他分享 >websocket如何建立

websocket如何建立

时间:2023-04-29 19:32:44浏览次数:43  
标签:err websocket log nil 建立 如何 WebSocket conn

websocket是什么


WebSocket是一种计算机通信协议,它提供了在单个TCP连接上进行全双工通信的能力。它允许客户端和服务器之间进行实时数据交换,可以用于实现在线游戏、聊天室、股票市场等需要实时通信的应用程序。WebSocket协议是HTML5规范的一部分,支持大部分现代浏览器。


如何建立长连接


使用Golang建立长连接可以使用标准库中的netwebsocket包。

以下是一个基本的示例,它创建一个WebSocket服务器并接受客户端连接:

package main

import (
    "log"
    "net/http"

    "github.com/gorilla/websocket"
)

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

func echo(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println(err)
        return
    }
    defer conn.Close()

    for {
        // 读取客户端发来的消息
        _, message, err := conn.ReadMessage()
        if err != nil {
            log.Println(err)
            break
        }
        // 将消息原样返回给客户端
        err = conn.WriteMessage(websocket.TextMessage, message)
        if err != nil {
            log.Println(err)
            break
        }
    }
}

func main() {
    http.HandleFunc("/echo", echo)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

在此示例中,我们使用Upgrader结构体将HTTP请求升级为WebSocket连接。然后,我们在一个无限循环中读取客户端发送的消息,并将消息原样发送回客户端。


客户端如何跟服务器建立长连接


在Golang中,客户端可以使用gorilla/websocket包来与WebSocket服务器建立长连接。以下是一个示例代码:

package main

import (
    "log"
    "net/url"
    "os"
    "os/signal"
    "time"

    "github.com/gorilla/websocket"
)

func main() {
    interrupt := make(chan os.Signal, 1)
    signal.Notify(interrupt, os.Interrupt)

    u := url.URL{Scheme: "ws", Host: "localhost:8080", Path: "/echo"}
    log.Printf("connecting to %s", u.String())

    c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
    if err != nil {
        log.Fatal("dial:", err)
    }
    defer c.Close()

    done := make(chan struct{})

    // 接收来自服务器的消息
    go func() {
        defer close(done)
        for {
            _, message, err := c.ReadMessage()
            if err != nil {
                log.Println("read:", err)
                return
            }
            log.Printf("recv: %s", message)
        }
    }()

    // 发送消息给服务器
    ticker := time.NewTicker(time.Second)
    defer ticker.Stop()

    for {
        select {
        case <-done:
            return
        case <-ticker.C:
            err := c.WriteMessage(websocket.TextMessage, []byte("hello"))
            if err != nil {
                log.Println("write:", err)
                return
            }
        case <-interrupt:
            log.Println("interrupt")
            // 优雅关闭连接
            err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
            if err != nil {
                log.Println("write close:", err)
                return
            }
            select {
            case <-done:
            case <-time.After(time.Second):
            }
            return
        }
    }
}

在此示例中,我们使用websocket.DefaultDialer拨号WebSocket服务器,并使用ReadMessageWriteMessage方法发送和接收消息。使用interrupt通道进行优雅关闭。

要注意的是,此示例中的路径/echo是服务器端实现的WebSocket处理程序的路径。


这个错误通常是由于客户端没有正确设置请求头引起的。WebSocket连接需要使用HTTP请求升级协议,这需要在请求头中指定UpgradeConnection头字段。

在Golang中,可以使用net/http包中的Header类型来设置请求头。以下是一个示例代码:

package main

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

    "github.com/gorilla/websocket"
)

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

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        conn, err := upgrader.Upgrade(w, r, nil)
        if err != nil {
            log.Println("upgrade:", err)
            return
        }
        defer conn.Close()

        for {
            _, message, err := conn.ReadMessage()
            if err != nil {
                log.Println("read:", err)
                break
            }
            log.Printf("recv: %s", message)
            err = conn.WriteMessage(websocket.TextMessage, []byte(fmt.Sprintf("echo: %s", message)))
            if err != nil {
                log.Println("write:", err)
                break
            }
        }
    })

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

在客户端代码中,需要使用http.Header类型来设置请求头。以下是一个示例代码:

package main

import (
    "log"
    "net/http"

    "github.com/gorilla/websocket"
)

func main() {
    url := "ws://localhost:8080/"

    header := http.Header{}
    header.Add("Connection", "upgrade")
    header.Add("Upgrade", "websocket")

    conn, _, err := websocket.DefaultDialer.Dial(url, header)
    if err != nil {
        log.Fatal("dial:", err)
    }
    defer conn.Close()

    err = conn.WriteMessage(websocket.TextMessage, []byte("hello"))
    if err != nil {
        log.Println("write:", err)
        return
    }

    _, message, err := conn.ReadMessage()
    if err != nil {
        log.Println("read:", err)
        return
    }
    log.Printf("recv: %s", message)
}

在此示例中,我们使用http.Header类型设置了UpgradeConnection头字段,以使客户端请求被正确升级为WebSocket连接。


如何验证websocket是否已经建立


在Golang中,可以使用*websocket.Conn类型的ReadMessage()WriteMessage()方法来发送和接收WebSocket消息。这些方法将返回error类型的值,如果在发送或接收过程中出现错误,则返回非nil的错误。

如果需要验证WebSocket连接是否已经建立,可以使用WriteMessage()方法向服务器发送一个握手消息,并在发送之后读取服务器的响应消息。以下是一个示例代码:

package main

import (
    "log"

    "github.com/gorilla/websocket"
)

func main() {
    url := "ws://localhost:8080/"

    conn, _, err := websocket.DefaultDialer.Dial(url, nil)
    if err != nil {
        log.Fatal("dial:", err)
    }
    defer conn.Close()

    // 发送握手消息并等待响应
    if err := conn.WriteMessage(websocket.TextMessage, []byte("hello")); err != nil {
        log.Fatal("write:", err)
    }

    _, message, err := conn.ReadMessage()
    if err != nil {
        log.Fatal("read:", err)
    }

    // 验证WebSocket连接已经建立
    if string(message) == "connected" {
        log.Println("WebSocket连接已经建立")
    } else {
        log.Println("WebSocket连接未能建立")
    }
}

在此示例中,我们使用WriteMessage()方法向服务器发送一个包含"hello"消息体的WebSocket消息,并使用ReadMessage()方法等待服务器的响应。如果服务器返回的消息是"connected",则表明WebSocket连接已经建立。

标签:err,websocket,log,nil,建立,如何,WebSocket,conn
From: https://blog.51cto.com/u_15855860/6236836

相关文章

  • 如何判断直线模组的质量?
    直线模组作为自动化设备中重要的传动元件,相信大家都接触过它,并对其有一定的了解,但是对于采购人员来说,如何选择直线模组是一个难题,主要是现在的直线模组的需求量在不断地增加,直线模组的品牌也越来越多,简直让人眼花缭乱。怎么去选择一个好的直线模组?首先我们得懂得如何去判断直线模组......
  • Rust: CTP的rust版本如何手工封装
    https://blog.csdn.net/wowotuo/article/details/86669758这里指的手工封装,是指不用外部类似swig专用的库。一、库、配置1、DLL交互的库(1)libloadinghttps://github.com/nagisa/rust_libloading(2)libcRawFFIbindingstoplatformlibrarieslikelibc.https://github.com/rust-......
  • jenkins如何配置邮件
    看板--系统管理--配置......
  • 博客园中如何使用HTML所见即可得编辑器TinyMCE
    大纲基本内容:文本、段落规范结构:标题、大纲大量数据:表格、列表内外跳转:链接、锚点视觉媒体:图像、视频、音乐用户交流:表单、交互文本字体、大小、前景色、背景色、加粗、倾斜、下划线、中划线、清楚格式段落段落行间距、段落字间距、段落居中对其、段落居左对齐、......
  • Pytorch2 如何通过算子融合和 CPU/GPU 代码生成加速深度学习
    动动发财的小手,点个赞吧!PyTorch中用于图形捕获、中间表示、运算符融合以及优化的C++和GPU代码生成的深度学习编译器技术入门计算机编程是神奇的。我们用人类可读的语言编写代码,就像变魔术一样,它通过硅晶体管转化为电流,使它们像开关一样工作,并允许它们实现复杂的逻辑——这......
  • 关于京东详情接口如何对接
    京东详情接口是京东购物平台提供的一个重要接口,通过该接口可以获取到商品的详细信息。如果你在开发电商网站或者APP,需要使用到京东的商品信息,那么就需要对接京东详情接口。本文将介绍京东详情接口的使用步骤。一、准备工作在使用京东详情接口之前,需要先注册为京东开发者,然后在京东......
  • 商品详情API接口如何获取淘宝数据
    淘宝是中国最大最受欢迎的电商平台之一,汇集了大量的商家和买家。在淘宝上热门商品的销量经常十分巨大,因此有些开发者和网站想要获取淘宝商品数据来进行一些分析。下面是一篇关于淘宝商品详情API接口获取淘宝数据的文章。一、淘宝商品API接口介绍淘宝开放了API接口,允许开发者获取淘......
  • 如何减少过拟合?
    过拟合即过度拟合train集分布,泛化能力差解决方案正则化L0,L1,L2dropoutearlystop数据增强正则化正则化是一类通过限制模型复杂度,从而避免过拟合,提高泛化能力的方法,包括引入一些约束规则,增加先验、提前停止等。L0,L1,L2正则化指给目标函数增加关于模型权重......
  • 如何搭建表白墙网站(LoveWall),Linux搭建网站教程
    用宝塔面板和开源表白墙程序LoveWall搭建一个表白墙网站。LoveWall是一个基于Thinkphp开发的表白墙。特色功能点赞发评论发弹幕多校区分享页涉证、涉H、暴力、违禁物等名词进行检测waitUpdate。下面是搭建教程:一、注册域名域名就是你的网站的网址,比如:blog.zeruns.tech就是我......
  • ETL数据仓测试如何测试
     在我们了解ETL测试之前,先了解有关商业智能和数据仓库的重要性。让我们开始吧-什么是BI?商业智能是收集原始数据或业务数据并将其转化为有用和更有意义的信息的过程。原始数据是一个组织每日事务的记录,如与客户的互动,财务管理和员工管理等。这些数据将用于“报告,分析,数据挖掘,......