Heim >Backend-Entwicklung >Golang >Wie kann ich das Message Framing mit net.Conn.Read in Go für persistente TCP-Sockets zuverlässig handhaben?

Wie kann ich das Message Framing mit net.Conn.Read in Go für persistente TCP-Sockets zuverlässig handhaben?

Susan Sarandon
Susan SarandonOriginal
2024-11-27 12:49:10356Durchsuche

How to Reliably Handle Message Framing with net.Conn.Read in Go for Persistent TCP Sockets?

Richtige Verwendung von net.Conn.Read für persistente TCP-Sockets

In Go umfasst die Arbeit mit persistenten TCP-Sockets den kontinuierlichen Aufbau einer Verbindung Eingehende Daten lesen. Die net.Conn.Read-Funktion ist für das Abrufen von Daten aus dem Socket verantwortlich, ihr Verhalten ist jedoch möglicherweise nicht sofort klar.

Nachrichtenframing in TCP verstehen

Im Gegensatz zu einigen anderen Im Gegensatz zu anderen Protokollen bietet TCP grundsätzlich kein Nachrichten-Framing. Dies bedeutet, dass es Sache der Anwendung ist, eine Methode zum Trennen von Nachrichten innerhalb des kontinuierlichen Datenstroms zu definieren.

Traditionelles Message Framing mit Header

In Ihrer bisherigen C#-Erfahrung: Den Nachrichten wurde ein Header mit der Nachrichtengröße vorangestellt. Dieser Ansatz ermöglicht es der empfangenden Anwendung, die genaue Länge der nachfolgenden Nachricht zu kennen.

Wie Go die Nachrichtenverarbeitung handhabt

Go verfolgt einen anderen Ansatz. Standardmäßig verfügt net.Conn.Read() nicht über einen inhärenten Mechanismus, um das Ende einer Nachricht zu bestimmen. Der Codeausschnitt, den Sie in Ihrer Frage angegeben haben, ruft einfach conn.Read() in einer Schleife auf, ohne Nachrichtengrenzen zu berücksichtigen. Dies kann für bestimmte Szenarien funktionieren, ist aber keine zuverlässige oder skalierbare Lösung.

Lösung: Benutzerdefiniertes Nachrichten-Framing

Um persistente TCP-Sockets richtig zu handhaben, müssen Sie Folgendes implementieren Benutzerdefinierter Nachrichtenrahmen. Dazu gehört das Puffern der eingehenden Daten und das Parsen gemäß Ihrem eigenen definierten Protokoll.

Beispiel mit bufio.Reader

Ein empfohlener Ansatz ist die Verwendung des integrierten bufio .Reader zum Einwickeln Ihres Netzes.Conn. Dieser Wrapper bietet zusätzliche Funktionalität und macht das Lesen von Daten effizienter.

import (
    "bufio"
    "fmt"
    "io"
    "net"
)

func main() {
    listener, err := net.Listen("tcp", ":8080")
    if err != nil {
        panic(err)
    }

    for {
        conn, err := listener.Accept()
        if err != nil {
            continue
        }

        go handleConnection(conn)
    }
}

func handleConnection(conn net.Conn) {
    defer conn.Close()
    r := bufio.NewReader(conn)

    for {
        size, err := r.ReadByte()
        if err != nil {
            return
        }

        buff := make([]byte, size)
        if _, err := io.ReadFull(r, buff); err != nil {
            return
        }

        fmt.Println("Received:", buff)
    }
}

In diesem Beispiel liest die Funktion handleConnection zunächst ein einzelnes Byte aus der Verbindung, das die Länge der nachfolgenden Nachricht darstellt. Anschließend wird ein Puffer erstellt und io.ReadFull verwendet, um die vollständige Nachricht der angegebenen Größe zu lesen. Dadurch kann die Anwendung Nachrichten unterschiedlicher Länge nahtlos verarbeiten.

Das obige ist der detaillierte Inhalt vonWie kann ich das Message Framing mit net.Conn.Read in Go für persistente TCP-Sockets zuverlässig handhaben?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn