【发布时间】:2018-11-11 12:34:39
【问题描述】:
今天当我尝试向我的服务器(一个非常简单的 TCP 服务器,也是用 Golang 编写的)发送 100M 数据时,我发现 TCPConn.Write 方法返回 104857600 和 nil 错误,然后我关闭了套接字。但是我的服务器只接收到很少的数据。我想是因为Write方法工作在异步模式下,所以虽然方法返回104857600,但是只有很少的数据发送到服务器。所以我想知道是否有办法将Write工作设置为同步模式,或者如何检测是否所有数据都从套接字发送到服务器。
代码如下: 服务器:
const ListenAddress = "192.168.0.128:8888"
func main() {
var l net.Listener
var err error
l, err = net.Listen("tcp", ListenAddress)
if err != nil {
fmt.Println("Error listening:", err)
os.Exit(1)
}
defer l.Close()
fmt.Println("listen on " + ListenAddress)
for {
conn, err := l.Accept()
if err != nil {
fmt.Println("Error accepting: ", err)
os.Exit(1)
}
//logs an incoming message
fmt.Printf("Received message %s -> %s \n", conn.RemoteAddr(), conn.LocalAddr())
// Handle connections in a new goroutine.
go handleRequest(conn)
}
}
func handleRequest(conn net.Conn) {
defer conn.Close()
rcvLen := 0
rcvData := make([]byte,20 * 1024 * 1024) // 20M
for {
l , err := conn.Read(rcvData)
if err != nil {
fmt.Printf("%v", err)
return
}
rcvLen += l
fmt.Printf("recv: %d\r\n", rcvLen)
conn.Write(rcvData[:l])
}
}
客户:
conn, err := net.Dial("tcp", "192.168.0.128:8888")
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
defer conn.Close()
data := make([]byte, 500 * 1024 * 1024)
len, err := conn.Write(data)
fmt.Println("send len: ", len)
客户端的输出:
send len: 524288000
服务器的输出:
listen on 192.168.0.128:8888
Received message 192.168.0.2:50561 -> 192.168.0.128:8888
recv: 166440
recv: 265720
EOF
我知道如果我可以通过 SetLinger 方法让客户端等待一段时间,数据将在套接字关闭之前全部发送到服务器。但我想找到一种方法让套接字在返回之前发送所有数据而不调用 SetLinger()。提前致谢。请原谅我的英语不好。
【问题讨论】:
-
写入不是异步的。是什么让您认为您的“服务器只接收很少的数据”?不管你认为你的代码多么简单,它仍然可能是不正确的。请务必将其包含在问题中。
-
"检测是否所有数据都从套接字发送到服务器。" - 您是否真的想知道是否所有数据都已发送(并且可能仍在传输中并且可能会在那里丢失)或者您是否想知道是否所有数据都已收到并且可能还由服务器处理?我的猜测是最后一种情况,在这种情况下您需要服务器发回某种确认。
-
@Peter 我添加了我的代码。请看一看。我仍然对这个问题感到困惑。谢谢。
-
@SteffenUllrich 我只想确保在 Write() 返回之前发送所有数据。
标签: sockets asynchronous go