golang实现Go与JavaScript强大Socket通信的插件库Glue的使用

Golang实现Go与JavaScript强大Socket通信的插件库Glue的使用

Glue简介

Glue是一个实时双向Socket通信库,是socket.io的一个简洁健壮高效的替代方案。这个库旨在以简单的方式连接Web浏览器和Go后端。

主要特性

  • 自动检测支持的Socket层并选择最合适的
  • 处理断开连接时的自动重连
  • 服务器实现是线程安全稳定
  • API是固定的,不会有破坏性的API变更

支持的Socket层

目前支持两种Socket层:

  1. WebSockets - 主要选项,如果浏览器支持RFC 6455定义的WebSocket则使用
  2. AjaxSockets - 作为回退模式使用

安装

客户端

客户端JavaScript Glue库位于client/dist/glue.js

可以使用bower安装客户端库:

bower install --save glue-socket

服务器端

获取源代码并开始使用:

go get github.com/desertbit/glue

导入:

import "github.com/desertbit/glue"

完整示例

客户端示例

<script>
    // 创建并连接到服务器
    // 可选传递主机字符串和选项
    var socket = glue();

    socket.onMessage(function(data) {
        console.log("onMessage: " + data);

        // 将消息回显给服务器
        socket.send("echo: " + data);
    });

    socket.on("connected", function() {
        console.log("connected");
    });

    socket.on("connecting", function() {
        console.log("connecting");
    });

    socket.on("disconnected", function() {
        console.log("disconnected");
    });

    socket.on("reconnecting", function() {
        console.log("reconnecting");
    });

    socket.on("error", function(e, msg) {
        console.log("error: " + msg);
    });

    socket.on("connect_timeout", function() {
        console.log("connect_timeout");
    });

    socket.on("timeout", function() {
        console.log("timeout");
    });

    socket.on("discard_send_buffer", function() {
        console.log("some data could not be send and was discarded.");
    });
</script>

服务器端示例

import (
    "log"
    "net/http"

    "github.com/desertbit/glue"
)

func main() {
    // 创建一个新的glue服务器
    server := glue.NewServer(glue.Options{
        HTTPListenAddress: ":8080",
    })

    // 在defer时释放glue服务器
    // 这将阻止新的传入连接
    // 并关闭所有当前活动的socket
    defer server.Release()

    // 设置glue事件函数来处理新的传入socket连接
    server.OnNewSocket(onNewSocket)

    // 运行glue服务器
    err := server.Run()
    if err != nil {
        log.Fatalf("Glue Run: %v", err)
    }
}

func onNewSocket(s *glue.Socket) {
    // 设置一个函数,在socket关闭时触发
    s.OnClose(func() {
        log.Printf("socket closed with remote address: %s", s.RemoteAddr())
    })

    // 设置一个函数,在每个接收到的消息时触发
    s.OnRead(func(data string) {
        // 将接收到的数据回显给客户端
        s.Write(data)
    })

    // 向客户端发送欢迎字符串
    s.Write("Hello Client")
}

通道(Channels)使用

通道是从客户端到服务器的单个socket连接的独立通信通道。可以创建多个独立的通信通道:

服务器端

// 创建一个通道
c := s.Channel("golang")

// 设置通道的读取事件函数
c.OnRead(func(data string) {
    // ...
})

// 写入通道
c.Write("Hello Gophers!")

客户端

var c = socket.channel("golang");

c.onMessage(function(data) {
    console.log(data);
});

c.send("Hello World");

广播消息

使用Glue可以轻松地向多个客户端广播消息。Glue服务器跟踪所有活动的客户端会话。您可以使用服务器的SocketsGetSocketOnNewSocket方法来实现广播。

自定义选项

客户端选项

var host = "https://foo.bar";

var opts = {
    // 基础URL附加到主机字符串。此值必须与服务器值匹配
    baseURL: "/glue/",

    // 强制使用特定的socket类型
    // 值: false, "WebSocket", "AjaxSocket"
    forceSocketType: false,

    // 在超时后终止连接尝试
    connectTimeout:  10000,

    // 如果连接空闲,ping服务器检查连接是否仍然存活
    pingInterval:           35000,
    // 如果服务器在超时内没有响应pong,则重新连接
    pingReconnectTimeout:   5000,

    // 是否在连接丢失时自动重新连接
    reconnect:          true,
    reconnectDelay:     1000,
    reconnectDelayMax:  5000,
    // 设置为0表示禁用(无限重试)
    reconnectAttempts:  10,

    // 在超时后重置发送缓冲区
    resetSendBufferTimeout: 10000
};

// 创建并连接到服务器
// 可选传递主机字符串和选项
var socket = glue(host, opts);

服务器端自定义HTTP多路复用器

// 创建一个新的glue服务器而不配置和启动HTTP服务器
server := glue.NewServer(glue.Options{
    HTTPSocketType: HTTPSocketTypeNone,
})

注意事项

  • 必须从socket和每个通道读取数据。如果您不需要从socket或通道读取数据,则使用DiscardRead()方法丢弃接收到的数据
  • 如果接收到的数据没有被丢弃,则当读取缓冲区满时会被阻塞,这也会阻塞socket的keep-alive机制,结果会导致socket关闭

更多关于golang实现Go与JavaScript强大Socket通信的插件库Glue的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现Go与JavaScript强大Socket通信的插件库Glue的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Glue: Go与JavaScript的Socket通信插件库

Glue是一个强大的Go库,用于实现Go后端与前端JavaScript之间的WebSocket通信。下面我将详细介绍Glue的使用方法并提供示例代码。

Glue核心特性

  1. 双向实时通信
  2. 简单易用的API
  3. 自动重连机制
  4. 支持自定义消息处理
  5. 轻量级且高性能

安装Glue

go get github.com/desertbit/glue

基本使用示例

Go服务端代码

package main

import (
	"log"
	"net/http"

	"github.com/desertbit/glue"
)

func main() {
	// 创建HTTP服务器
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, "index.html")
	})

	// 创建Glue服务器
	socket := glue.NewServer(glue.Options{
		HTTPSocket: "/socket",
	})

	// 处理新连接
	socket.OnNewSocket(func(s *glue.Socket) {
		log.Printf("新客户端连接: %s", s.ID())

		// 处理接收到的消息
		s.OnRead(func(data string) {
			log.Printf("来自 %s 的消息: %s", s.ID(), data)
			
			// 回复客户端
			s.Write("服务器收到: " + data)
		})

		// 处理断开连接
		s.OnClose(func() {
			log.Printf("客户端断开: %s", s.ID())
		})
	})

	// 将Glue服务器附加到HTTP服务器
	http.Handle(socket.NetHTTPSocket(), socket)

	// 启动服务器
	log.Println("服务器启动在 :8080")
	log.Fatal(http.ListenAndServe(":8080", nil))
}

JavaScript客户端代码

<!DOCTYPE html>
<html>
<head>
    <title>Glue示例</title>
    <script src="//cdn.jsdelivr.net/glue/latest/glue.min.js"></script>
</head>
<body>
    <script>
        // 创建Socket连接
        var socket = new GlueSocket('/socket');
        
        // 连接成功回调
        socket.on('open', function() {
            console.log('连接服务器成功');
            
            // 发送消息到服务器
            socket.send('Hello from JavaScript!');
        });
        
        // 接收消息回调
        socket.on('message', function(data) {
            console.log('收到服务器消息:', data);
        });
        
        // 错误处理
        socket.on('error', function(err) {
            console.error('Socket错误:', err);
        });
        
        // 连接关闭
        socket.on('close', function() {
            console.log('连接已关闭');
        });
    </script>
</body>
</html>

高级功能示例

自定义消息类型

// Go服务端
s.OnRead(func(data string) {
    // 解析JSON消息
    var msg struct {
        Type    string `json:"type"`
        Content string `json:"content"`
    }
    
    if err := json.Unmarshal([]byte(data), &msg); err != nil {
        log.Printf("消息解析错误: %v", err)
        return
    }
    
    switch msg.Type {
    case "chat":
        log.Printf("聊天消息: %s", msg.Content)
        s.Write(`{"type": "ack", "status": "received"}`)
    case "command":
        log.Printf("命令: %s", msg.Content)
        // 处理命令...
    }
})
// JavaScript客户端
function sendChatMessage(text) {
    socket.send(JSON.stringify({
        type: 'chat',
        content: text
    }));
}

// 发送聊天消息
sendChatMessage('你好,服务器!');

广播消息

// Go服务端广播给所有客户端
socket.OnNewSocket(func(s *glue.Socket) {
    // 存储所有连接的socket
    sockets[s.ID()] = s
    
    s.OnClose(func() {
        delete(sockets, s.ID())
    })
})

func broadcast(msg string) {
    for _, s := range sockets {
        s.Write(msg)
    }
}

二进制数据传输

// Go服务端发送二进制数据
s.OnRead(func(data string) {
    // 发送二进制数据
    binaryData := []byte{0x48, 0x65, 0x6c, 0x6c, 0x6f} // "Hello"的二进制
    s.WriteBinary(binaryData)
})
// JavaScript客户端接收二进制数据
socket.on('binary', function(data) {
    console.log('收到二进制数据:', data);
    // 可以转换为文本
    var text = new TextDecoder().decode(data);
    console.log('转换为文本:', text);
});

最佳实践

  1. 心跳机制:实现心跳检测以确保连接活跃
  2. 错误处理:妥善处理连接错误和重连
  3. 消息协议:定义清晰的消息协议格式
  4. 限流:对客户端消息频率进行限制
  5. 安全:实现身份验证和授权

Glue提供了强大而简单的API,使得Go与JavaScript之间的实时通信变得非常容易。通过上述示例,您可以快速构建实时应用程序如聊天系统、实时数据监控等。

回到顶部