How to fully read buffered content from tcp socket after closing client connection?

PHPz
Release: 2024-02-11 16:33:18
forward
451 people have browsed it

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

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.

Question content

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)
}
Copy after login

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]
Copy after login

Solution

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!

Related labels:
source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!