Wie kann ich gepufferten Inhalt vollständig aus dem TCP-Socket lesen, nachdem die Client-Verbindung geschlossen wurde?

PHPz
Freigeben: 2024-02-11 16:33:18
nach vorne
451 Leute haben es durchsucht

关闭客户端连接后如何从 tcp 套接字完全读取缓冲内容?

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.

Frageninhalt

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)
}
Nach dem Login kopieren

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]
Nach dem Login kopieren

Workaround

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!

Verwandte Etiketten:
Quelle:stackoverflow.com
Erklärung dieser Website
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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!