Flutter 和 Go 建立 WebSocket 链接,有什么方案?

73 min read

可以使用 WebSocket 的客户端库来建立链接。

对于 Flutter,可以使用 web_socket_channel 库来建立 WebSocket 链接。

示例代码:

import 'package:flutter/material.dart';
import 'package:web_socket_channel/io.dart';

class WebSocketPage extends StatefulWidget {
  @override
  _WebSocketPageState createState() => _WebSocketPageState();
}

class _WebSocketPageState extends State<WebSocketPage> {
  final channel = IOWebSocketChannel.connect('ws://localhost:8000');

  @override
  void dispose() {
    channel.sink.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('WebSocket Demo'),
      ),
      body: StreamBuilder(
        stream: channel.stream,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return Text(snapshot.data.toString());
          } else {
            return Center(
              child: CircularProgressIndicator(),
            );
          }
        },
      ),
    );
  }
}

对于 Go,可以使用官方的 net/http 包中的 websocket 子包来建立 WebSocket 链接。

示例代码:

package main

import (
	"fmt"
	"net/http"

	"github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool { return true },
}

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

	for {
		_, message, err := conn.ReadMessage()
		if err != nil {
			fmt.Println(err)
			return
		}
		fmt.Println(string(message))

		err = conn.WriteMessage(websocket.TextMessage, []byte("pong"))
		if err != nil {
			fmt.Println(err)
			return
		}
	}
}

func main() {
	http.HandleFunc("/", handler)
	fmt.Println("Listening on localhost:8000")
	http.ListenAndServe(":8000", nil)
}

这个示例程序是一个简单的 WebSocket 服务器,接收客户端发送的消息并回复 "pong"。可以在 Flutter 中使用web_socket_channel 客户端库来测试这个服务器。

示例代码:

import 'package:flutter/material.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

class WebSocketPage extends StatefulWidget {
  @override
  _WebSocketPageState createState() => _WebSocketPageState();
}

class _WebSocketPageState extends State<WebSocketPage> {
  final channel = WebSocketChannel.connect(Uri.parse('ws://localhost:8000'));

  @override
  void dispose() {
    channel.sink.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('WebSocket Demo'),
      ),
      body: StreamBuilder(
        stream: channel.stream,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return Text(snapshot.data.toString());
          } else {
            return Center(
              child: CircularProgressIndicator(),
            );
          }
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          channel.sink.add('ping');
        },
        child: Icon(Icons.arrow_upward),
      ),
    );
  }
}