我有 2 個進程通過 TCP 套接字進行通信。A 方向 B 方發送字符串,有時使用標準加密/密碼包對其進行加密。生成的字符串可能包含換行符,但 B 方的 bufio 掃描器將其解釋為請求的結束。我希望 B 方繼續接受行、追加它們并等待已知的命令結束字符,然后再進一步處理它。B 方將向 A 方返回響應,因此連接保持打開狀態,因此不能使用關閉連接事件作為命令分隔符。對于單行命令,一切工作正常,但加密輸出中的這些新行字符會導致問題(大約 10% 的情況)。A 方將以以下格式發送(第三個是我試圖正確處理的問題字符串的合法示例):調用命令()callCommand("一","二","三")callCommand("string","要關注的加密數據","[7b??Cr??l??G????bH?@x????????? ?(z?$? a??0??帶5Y7+??U?QT??l?K?(?n?U??J????QK?BX?+?l\8H??-g?y.?.?1? f??I?C??????o?xz?8???c?e ?Tb??4?hD W??? ?<???Е?gc?????? ?N?V??P8 ???O3")我們可以相當可靠地說命令結束鍵是右括號“)”和換行符。A方發送給B方的功能:func writer(text string) string { conn, err := net.Dial("tcp", TCPdest) t := time.Now() if err != nil { if _, t := err.(*net.OpError); t { fmt.Println("Some problem connecting.\r\n") } else { fmt.Println("Unknown error: " + err.Error()+"\r\n") } } else { conn.SetWriteDeadline(time.Now().Add(1 * time.Second)) _, err = conn.Write([]byte(text+"\r\n")) if err != nil { fmt.Println("Error writing to stream.\r\n") } else { timeNow := time.Now() if timeNow.Sub(t.Add(time.Duration(5*time.Second))).Seconds() > 5 { return "timeout" } scanner := bufio.NewScanner(conn) for { ok := scanner.Scan() if !ok { break } if strings.HasPrefix(scanner.Text(), "callCommand(") && strings.HasSuffix(scanner.Text(), ")") { conn.Close() return scanner.Text() } } } } return "unspecified error"}B方對傳入連接的處理:src := "192.168.68.100:9000"listener, _ := net.Listen("tcp", src)defer listener.Close()for { conn, err := listener.Accept() if err != nil { fmt.Println("Some connection error: %s\r\n", err) } go handleConnection(conn)} 我不太確定 B 面的這種方法是否正確,但在上面包含了我的代碼。我見過一些實現,但很多似乎依賴于關閉連接來開始處理請求,這不適合我的場景。
1 回答

萬千封印
TA貢獻1891條經驗 獲得超3個贊
您的通信“協議”(一行是一條消息,不完全是協議)顯然無法處理二進制數據。如果您想在協議中發送文本數據,您可以將二進制數據轉換為文本,例如使用 Base64 編碼。您還需要一些語義來指示某些文本是從二進制轉換而來的。
或者您可以更改協議以本地處理二進制數據。您可以在后面添加二進制數據的長度,這樣您就知道必須以二進制形式讀取該數據,而不是將換行符解釋為消息的結尾。
有許多協議在這方面做得很好,也許您不需要想出您的自定義協議。如果你想發送短信,HTTP 使用起來非常簡單,你可以將數據格式化為 JSON,使用 Base64 將二進制數據轉換為文本:
{
"command": "string",
"args": [
"binaryDataAsBase64"
]
}
- 1 回答
- 0 關注
- 138 瀏覽
添加回答
舉報
0/150
提交
取消