1. 项目地址:

    # 服务端
    https://github.com/googollee/go-socket.io
    # 客户端(go)
    https://github.com/zhouhui8915/go-socket.io-client
    # 客户端(javascript)
    https://cdnjs.com/libraries/socket.io
  2. websocket 在线调试工具:
    https://www.lddgo.net/network/websocket

  3. socket.io 相关概念:

     1. 命名空间:相当于 url 下的不同路径;
     2. 广播
     3. 房间
     4. 自定义事件
  4. 示例代码:

    1. go 服务器:
       package main
       import (
           "fmt"
           "log"
           "net/http"
           "github.com/googollee/go-socket.io"
           "net/url"
       )
       func main() {
           server, err := socketio.NewServer(nil)
           if err != nil {
               log.Fatal(err)
           }
           ///////////////////////////////////////////////////////////
           // 命名空间:/chat 下
           server.OnConnect("/chat", func(s socketio.Conn) error {
               s.SetContext("消息传递")
               fmt.Println("connected:", s.ID())
               // 获取查询参数
               params,_ := url.ParseQuery(s.URL().RawQuery)
               username := params.Get("username")
               password := params.Get("password")
               fmt.Println(username,password)
               s.Join("room")  // 加入房间
               return nil
           })
           server.OnEvent("/chat", "msg:1", func(s socketio.Conn, msg string) {
               fmt.Println(msg,s.Context())
               s.Emit("msg:1", "world - 1")  // 服务端发送消息:只给当前连接的用户发送消息
               s.Close()  // 服务端主动断开与当前用户的连接
           })
           server.OnEvent("/chat", "msg:2", func(s socketio.Conn, msg string) {
               fmt.Println(msg)
               server.BroadcastToRoom("/chat", "room", "msg:2", "world - 2")  // 服务端发送消息:给所有加入房间的用户发送消息
           })
           // 失去连接事件,可以做一些登出操作
           server.OnDisconnect("/", func(s socketio.Conn, reason string) {
               fmt.Println("closed", reason)
           })
           ///////////////////////////////////////////////////////////
           // 错误处理事件,可忽略
           server.OnError("/", func(s socketio.Conn, e error) {
               fmt.Println("meet error:", e)
           })
           go server.Serve()
           defer server.Close()
           // 登录功能:localhost:8000/login
           http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
               w.Header().Set("Access-Control-Allow-Origin", "*")             // 允许访问所有域
               w.Header().Add("Access-Control-Allow-Headers", "Content-Type")  // header的类型
               w.Header().Set("content-type", "application/json")             // 返回数据格式是json
               fmt.Println("login")  // 输出到控制台
               fmt.Fprintf(w, "login")  // 输出到客户端
           })
           // 文件上传功能:localhost:8000/upload
           http.HandleFunc("/upload", func(w http.ResponseWriter, r *http.Request) {
               fmt.Println("upload")  // 输出到控制台
               fmt.Fprintf(w, "upload")  // 输出到客户端
           })
           // 静态文件服务器:localhost:8000/test.txt  -->  ./file/test.txt
           http.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir("./file"))))
           // socket.io 核心功能
           http.HandleFunc("/socket.io/", func(w http.ResponseWriter, r *http.Request) {
               // 允许跨域
               origin := r.Header.Get("Origin")
               log.Println("origin",origin)
               w.Header().Set("Access-Control-Allow-Origin", origin)
               w.Header().Set("Access-Control-Allow-Credentials", "true")
               server.ServeHTTP(w, r)
           })
           log.Println("请打开网址: http://localhost:8080 进行访问...")
           log.Fatal(http.ListenAndServe(":8000", nil))
       }
    2. go 客户端(不支持命名空间〜〜):
       package main
       import (
           "fmt"
           "github.com/zhouhui8915/go-socket.io-client"
           "log"
           "time"
       )
       func main() {
           ticker := time.NewTicker(time.Second * 10)
           opts := &socketio_client.Options{
               Transport: "websocket",
               Query:     make(map[string]string),
           }
           uri := "http://localhost:8000"
           client, err := socketio_client.NewClient(uri, opts)
           if err != nil {
               log.Printf("NewClient error:%v\n", err)
               return
           }
           for{
               ////////////////////////////////////////////////
               // 发送消息
               client.Emit("msg:1","hello - 1")
               client.Emit("msg:2","hello - 2")
               // 接收消息
               client.On("msg:1", func(msg string) {
                   fmt.Println(msg)
               })
               client.On("msg:2", func(msg string) {
                   fmt.Println(msg)
               })
               ////////////////////////////////////////////////
               // 错误处理和连接失败消息,可忽略
               client.On("error", func() {
                   log.Printf("on error\n")
               })
               client.On("disconnection", func() {
                   log.Printf("on disconnect\n")
               })
               <- ticker.C
           }
       }
    3. js 客户端(官网说只支持版本 1.4.x 以下的…):
       <!doctype html>
       <html lang="en">
       <head>
           <meta charset="UTF-8">
           <meta name="viewport"
                 content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
           <meta http-equiv="X-UA-Compatible" content="ie=edge">
           <title>Document</title>
           <script src="jquery.min.js"></script>
           <script src="socket.io.js"></script>
       </head>
       <body>
       <script>
           // 使用 /chat 命名空间
           var socket = io('http://localhost:8000/chat',{
               query: {
                   username: 'username',
                   password: 'password',
               }
           });
           // 发送消息
           socket.emit('msg:1', "hello - 1")
           socket.emit('msg:2', "hello - 2")
           // 接收消息
           socket.on('msg:1',function(msg) {
               alert(msg)
           });
           socket.on('msg:2',function(msg) {
               alert(msg)
           });
       </script>
       </body>
       </html>
文档更新时间: 2024-04-20 10:57   作者:lee