在远程协作、在线教学、监控等场景中(当然啦!还有其他的用途,这里就不说了,懂得都懂),屏幕共享是一项非常重要的技术。本文将介绍如何使用Golang开发一个基于WebSocket的屏幕共享系统,实现远程查看电脑屏幕的功能。
技术原理
整个屏幕共享的流程如下:
- 定时截图:使用kbinani/screenshot 进行屏幕捕获,每隔100ms采集一次屏幕。
- 图片压缩:为了减少数据传输量,将截图压缩为 JPEG 格式。
- WebSocket传输:通过gorilla/websocket实现WebSocket服务器,将截图数据推送给浏览器客户端。
- 前端展示:浏览器通过WebSocket接收图像数据,并动态更新img标签以实时显示共享的屏幕内容。
后端实现
我们首先创建一个go项目并使用go编写一个WebSocket 服务器,用于捕获屏幕并实时发送给客户端,具体操作如下所示:
mkdir websocket-demo
cd websocket-demo/ && go mod init websocket-demo
# 安装 WebSocket 库
go get -u github.com/gorilla/websocket
# 安装屏幕截图库
go get -u github.com/kbinani/screenshot
然后键入如下代码,具体如下所示:
package main
import (
"bytes"
"fmt"
"image/jpeg"
"net/http"
"time"
"github.com/gorilla/websocket"
"github.com/kbinani/screenshot"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true }, // 允许跨域
}
// 捕获屏幕并转换为JPEG
func captureScreen() ([]byte, error) {
img, err := screenshot.CaptureDisplay(0) // 仅截取主屏幕
if err != nil {
return nil, err
}
buf := new(bytes.Buffer)
jpeg.Encode(buf, img, &jpeg.Options{Quality: 50}) // 50% 质量压缩
return buf.Bytes(), nil
}
// 处理WebSocket连接
func handleWS(conn *websocket.Conn) {
defer conn.Close()
for {
time.Sleep(100 * time.Millisecond) // 每100ms发送一次(10FPS)
imgData, err := captureScreen()
if err != nil {
fmt.Println("截图失败:", err)
continue
}
// 发送图片数据
if err = conn.WriteMessage(websocket.BinaryMessage, imgData); err != nil {
fmt.Println("发送失败:", err)
break
}
}
}
func main() {
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
fmt.Println("WebSocket连接失败:", err)
return
}
go handleWS(conn) // 处理WebSocket连接
})
fmt.Println("WebSocket 服务器启动,访问 ws://localhost:9527/ws")
http.ListenAndServe(":9527", nil)
}
代码解析
- screenshot.CaptureDisplay(0):获取主屏幕的截图。
- jpeg.Encode(buf, img, &jpeg.Options{Quality: 50}):将图片转换为JPEG格式并压缩,减少数据传输量。
- websocket.Upgrader:用于升级HTTP连接为WebSocket连接。
- handleWS(conn):不断循环截图并发送给WebSocket客户端。
⚠️注意: 需要提前安装好opencv相关依赖
前端实现
前端需要使用WebSocket接收屏幕图像数据,并动态更新img标签,具体事项如下所示:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>屏幕共享</title>
</head>
<body>
<h2>实时屏幕共享</h2>
<img id="screen" style="border: 1px solid black; width: 80%; max-width: 1024px;">
<script>
let ws = new WebSocket("ws://localhost:9527/ws");
let img = document.getElementById("screen");
ws.binaryType = "blob";
ws.onmessage = function (event) {
let url = URL.createObjectURL(event.data);
img.src = url;
};
ws.onclose = function () {
alert("连接已断开");
};
</script>
</body>
</html>
代码解析
let ws = new WebSocket(“ws://localhost:9527/ws”);:连接 WebSocket 服务器。
ws.onmessage = function (event) {…}:当收到屏幕图像数据时,创建 blob 对象,并更新 img 标签。
img.src = URL.createObjectURL(event.data);:动态显示截图。