Heim > Artikel > Backend-Entwicklung > Wie kann ich gepufferten Inhalt vollständig aus dem TCP-Socket lesen, nachdem die Client-Verbindung geschlossen wurde?
Bei der Netzwerkprogrammierung ist es ein häufiges Problem, den gepufferten Inhalt nach dem Schließen der Client-Verbindung vollständig aus dem TCP-Socket zu lesen. Wenn der Client die Verbindung schließt, sind möglicherweise noch ungelesene Daten auf der Serverseite vorhanden. Um sicherzustellen, dass der Pufferinhalt vollständig gelesen wird, können die folgenden Methoden verwendet werden: 1. Verwenden Sie das Schleifenlesen, bis das Datenende-Flag gelesen wird. 2. Setzen Sie ein Timeout und springen Sie aus der Schleife, wenn die Daten nicht innerhalb des gelesen werden 3. Verwenden Sie einen nicht blockierenden Socket und prüfen Sie durch Abfragen, ob Daten zum Lesen vorhanden sind. Mit der oben genannten Methode kann sichergestellt werden, dass der Pufferinhalt vollständig vom TCP-Socket gelesen wird, wodurch die Stabilität und Zuverlässigkeit der Netzwerkkommunikation verbessert wird.
Ich habe einen Go-Server, der einen TCP-Socket überwacht, und beim Herunterfahren möchte ich, dass er dem Client mitteilt, dass er keine weiteren Daten mehr senden soll, aber auch alles liest, was der Client bisher gesendet hat. Was ich sehe, ist, dass der Server nach dem Schließen der Client-Verbindung aufhört zu lesen, aber nie alles empfängt, was der Client zu senden glaubte. Was meiner Meinung nach passiert, ist, dass das Betriebssystem die empfangenen TCP-Pakete puffert und sie dann verwirft, wenn der Server die Client-Verbindung schließt.
Hier ist ein Programm, das das Problem zeigt. Der Server lauscht und druckt aus, was er empfängt; der Client sendet und druckt aus, was er sendet. Der Server unterbricht den Client, um ihn zu stoppen, aber am Ende möchte ich, dass die beiden Listen gleich sind.
Dieses Beispiel verwendet bufio.scanner, um den Socket zu lesen, aber ich habe auch versucht, nur Bytes aus der Verbindung zu lesen, habe aber das gleiche Ergebnis erhalten.
conn.(*net.tcpconn).closewrite()
Klingt nach genau dem, was ich will, aber das scheint den Kunden überhaupt nicht zu stören.
conn.(*net.tcpconn).setreadbuffer(0)
- Habe das auch versucht, aber 0 ist kein erlaubter Wert (Panik).
package main import ( "bufio" "fmt" "net" "strconv" "sync" "time" ) const port = ":8888" var wg sync.waitgroup func main() { wg.add(1) go func() { // wait for the server to start time.sleep(1000 * time.millisecond) client() }() // server listens wg.add(1) server() wg.wait() } func server() { defer wg.done() listener, err := net.listen("tcp", port) if err != nil { panic(err) } received := make([]string, 0) conn, err := listener.accept() if err != nil { panic(err) } defer conn.close() scanner := bufio.newscanner(conn) for i := 0; scanner.scan(); i++ { received = append(received, scanner.text()) // arbitrary condition: simulate a server shutdown - interrupt the client if len(received) == 2 { _ = conn.(*net.tcpconn).close() } } fmt.println("server received: ", received) } func client() { defer wg.done() conn, err := net.dial("tcp", port) if err != nil { panic(err) } sent := make([]string, 0) defer conn.close() for i := 0; i < 50000; i++ { v := strconv.itoa(i) _, err := conn.write([]byte(v + "\n")) if err != nil { fmt.println("client interrupted:", err) break } else { sent = append(sent, v) // slow down the sends to make output readable //time.sleep(1 * time.millisecond) } } fmt.println("client sent: ", sent) }
Die Ausgabe auf meiner Maschine sieht so aus:
Server received: [0 1 2] Client interrupted: write tcp 127.0.0.1:49274->127.0.0.1:8888: write: broken pipe Client sent: [0 1 2 3 4 5 6 7 8 9 10 11 12 13]
TCP bietet nur einen zuverlässigen bidirektionalen Bytestrom ohne inhärente Semantik. Wenn der Server möchte, dass der Client signalisiert, dass er keine Daten mehr senden soll, muss er diese Funktionalität als Teil des Anwendungsprotokolls implementieren, eine Schicht über dem reinen Datentransport, der von TCP bereitgestellt wird.
Das obige ist der detaillierte Inhalt vonWie kann ich gepufferten Inhalt vollständig aus dem TCP-Socket lesen, nachdem die Client-Verbindung geschlossen wurde?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!