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 套接字完全读取缓冲内容?的详细内容,更多请关注编程网其它相关文章!