php editor Xiaoxin In network programming, how to completely read the buffered content from the tcp socket after closing the client connection is a common problem. When the client closes the connection, there may still be unread data on the server side. In order to ensure complete reading of the buffer content, the following methods can be used: 1. Use loop reading until the data end flag is read; 2. Set a timeout and jump out of the loop if the data is not read within the specified time; 3. Use a non-blocking socket and check whether there is data to read by polling. The above method can ensure that the buffer content is completely read from the tcp socket, improving the stability and reliability of network communication.
I have a go server that is listening on a tcp socket, and during shutdown I want it to tell the client to stop sending more data, but also read the client so far Everything sent. What I see is that once the client connection is closed, the server stops reading, but it never receives everything the client thought it sent. What I think is happening is that the OS is buffering the received tcp packets and then discarding them when the server closes the client connection.
Here is a program that displays the problem. The server listens and prints out what it receives; the client sends and prints out what it sends. The server interrupts the client to stop it, but at the end I want both lists to be the same.
This example uses bufio.scanner to read the socket, but I've also tried just reading bytes from the connection and got the same results.
conn.(*net.tcpconn).closewrite()
Sounds like exactly what I want, but this doesn't seem to break the client at all.
conn.(*net.tcpconn).setreadbuffer(0)
- Tried this too, but 0 is not an allowed value (panic).
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) }
The output on my machine is like this:
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 only provides a reliable bidirectional byte stream without any inherent semantics. If the server wants the client to signal that it should no longer send any data, it must implement this functionality as part of the application protocol, a layer above the pure data transport provided by TCP.
The above is the detailed content of How to fully read buffered content from tcp socket after closing client connection?. For more information, please follow other related articles on the PHP Chinese website!