亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

<code id="nr6hm"></code>
  • <tt id="nr6hm"><thead id="nr6hm"><wbr id="nr6hm"></wbr></thead></tt>
  • <tt id="nr6hm"></tt>
    為了賬號安全,請及時綁定郵箱和手機立即綁定
    已解決430363個問題,去搜搜看,總會有你想問的

    TCP 客戶端或服務器卡在處理數據

    TCP 客戶端或服務器卡在處理數據

    Go
    滄海一幻覺 2022-09-19 10:43:17
    我正在嘗試編寫一個簡單的tcp服務器和客戶端程序。當我同時運行下面的服務器和客戶端代碼時,客戶端將僅接收來自服務器的時間消息并退出,并且服務器繼續接受新連接。我預期的程序行為是我希望服務器也從客戶端接收“hello world”消息并關閉連接,客戶端也使用“響應連接”功能也是如此。但問題是,當我啟動客戶端時,服務器似乎卡在了conn。讀取“響應連接”函數內的函數,當我首先停止客戶端時,錯誤為“EOF退出狀態1”,這對于調試來說確實是模棱兩可的。當我首先停止服務器時,客戶端將從服務器接收時間數據。如果您有任何想法,請幫助回答,因為我完全是Golang的新手。非常感謝!服務器.gopackage mainimport (    "fmt"    "io"    "log"    "net"    "time")type connection struct {    host    string    port    string    network string}func checkError(err error) {    if err != nil {        log.Fatalln(err)    }}func responseConnection(conn net.Conn) {    defer conn.Close() // <-- When responseConnection() is used, add this    buf := make([]byte, 0, 4096)    tmp := make([]byte, 256)    for {        n, err := conn.Read(tmp)        if err != nil {            checkError(err)            if err != io.EOF {                fmt.Println("Error reading: ", err)            }            // fmt.Println(err)            break        }        buf = append(buf, tmp[:n]...)    }    fmt.Println("Data from client ========> ", string(buf))    // c <- buf}func handleConnection(conn net.Conn) {    defer conn.Close() // <- When responseConnection() is used, remove this    dayTime := time.Now().String()    conn.Write([]byte(dayTime))    // responseConnection(conn)    fmt.Println("The end of handleConnection")}func main() {    localConn := connection{        host:    "",        port:    "5555",        network: "tcp",    }    // servicePort := ":5555"    tcpAddr, err := net.ResolveTCPAddr(localConn.network, ":"+localConn.port)    checkError(err)    l, err := net.ListenTCP("tcp", tcpAddr)    fmt.Println("Server starts listening on port", localConn.port)    checkError(err)        for {        fmt.Println("Accepting a new connection....")        conn, err := l.Accept()        checkError(err)        handleConnection(conn)        // responseConnection(conn)    }}
    查看完整描述

    1 回答

    ?
    慕桂英3389331

    TA貢獻2036條經驗 獲得超8個贊

    我認為你的問題非常標準:不注意TCP不實現消息邊界的事實,只是通過連接傳輸兩個不透明的字節流。

    這意味著,當您將一串字節“Hello world從客戶端”發送到連接的套接字(已建立的TCP連接)時,連接的另一端不知道客戶端的消息在哪里結束,除非客戶端以某種方式傳達它本身;根本沒有辦法使用TCP本身來劃分單個消息。

    輸入“應用程序級協議”:除非您打算使用TCP的數據交換任務自然地傳輸單個“消息” - 想象一下服務器將單個文件的內容轉儲到每個連接的客戶端并關閉連接 - 您必須發明一些方法讓客戶端告訴服務器它發送的每條消息實際上在哪里結束。

    考慮一下您的示例:在讀取過程中,您基本上有一個循環,該循環從套接字重復讀取數據塊,具有單個退出條件:到達該套接字上的文件末尾。只有當遠程端(在本例中為客戶端)關閉其連接端時,才會報告 EOF,而客戶端從不這樣做:它發送一個字符串,然后等待服務器發回一些東西,但服務器從不回復,因為它永遠不會完成讀取。

    有多種方法可以解決問題。

    • 發明一個自定義協議(例如,在TLV系列中),它將實現消息成幀。

      例如,在最簡單的形式中,該協議可以定義為單個無符號字節,其中包含以下消息的長度(以字節為單位)。
      然后,服務器將有一個兩步過程來讀取客戶端的每條消息:

      1. 讀取單個字節;

      2. 如果成功,請讀取由前導字節值定義的任意數量的后續字節;

      3. 成功后,請返回步驟 1 以閱讀以下消息。

    • 想出一個消息分隔符,如ASCII LF字符 - 可以編碼為Go的字符串文本,并使服務器繼續讀取,直到遇到LF;一旦它發現了一個LF,它就知道它應該處理消息,然后開始讀取另一個消息。\n

      圍棋有方便的類型布菲奧。讀取器在其標準包中,可以從由LF分隔的任何單個行中讀取。io.Reader

    • 具有更復雜的消息框架,例如使用 JSON 流發送 JSON 文檔。

      由庫存包實現的解碼器的一個經常監督的功能是,它可以解碼JSON對象的流,以此為例。encoding/json

    可能性實際上很多,所以我只是觸及了表面,我認為你應該明白這個想法。


    查看完整回答
    反對 回復 2022-09-19
    • 1 回答
    • 0 關注
    • 108 瀏覽
    慕課專欄
    更多

    添加回答

    舉報

    0/150
    提交
    取消
    微信客服

    購課補貼
    聯系客服咨詢優惠詳情

    幫助反饋 APP下載

    慕課網APP
    您的移動學習伙伴

    公眾號

    掃描二維碼
    關注慕課網微信公眾號