php小编小新在网络编程中,关闭客户端连接后,如何从tcp套接字完全读取缓冲内容是一个常见问题。当客户端关闭连接时,服务器端可能仍然存在未读取的数据。为了确保完整读取缓冲内容,可以采用以下几种方法:1.使用循环读取,直到读取到数据结束标志;2.设置超时时间,如果在规定时间内未读取到数据则跳出循环;3.使用非阻塞套接字,通过轮询检查是否有数据可读。以上方法可以保证从tcp套接字中完全读取缓冲内容,提升网络通信的稳定性和可靠性。
我有一个 go 服务器正在侦听 tcp 套接字,在关闭期间我希望它告诉客户端停止发送更多数据,但也读取客户端迄今为止发送的所有内容。我看到的是,一旦客户端连接关闭,服务器就会停止读取,但它永远不会收到客户端认为它发送的所有内容。我认为发生的情况是操作系统正在缓冲收到的 tcp 数据包,然后在服务器关闭客户端连接时丢弃它们。
这是一个显示该问题的程序。服务器监听,然后打印出它收到的内容;客户端发送并打印出发送的内容。服务器中断客户端以停止它,但最后我希望这两个列表相同。
此示例使用 bufio.scanner 读取套接字,但我也尝试过仅从连接读取字节,但得到相同的结果。
conn.(*net.tcpconn).closewrite()
听起来正是我想要的,但这似乎根本没有中断客户端。
conn.(*net.tcpconn).setreadbuffer(0)
- 也尝试过此操作,但 0 不是允许的值(恐慌)。
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) }
在我的机器上输出是这样的:
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仅提供可靠的双向字节流,没有任何固有语义。如果服务器希望客户端发出信号表明它不应再发送任何数据,则必须将此功能实现为应用程序协议的一部分,即 TCP 提供的纯数据传输之上的一层。
以上是关闭客户端连接后如何从 tcp 套接字完全读取缓冲内容?的详细内容。更多信息请关注PHP中文网其他相关文章!