【发布时间】:2018-03-31 22:59:55
【问题描述】:
我有一个测试函数,它既可以创建一个服务器,又可以生成一个作为客户端的 goroutine。现在,只需从客户端向服务器发送一条消息就可以了,但是如果我想创建一个交换,它们似乎会死锁,因为测试永远不会运行到完成(如果没有设置 r/w 截止日期)。例如,我希望客户端向服务器发送一条消息,服务器复制该消息并将其发送回客户端,然后客户端验证接收到的消息是否相同。这是我的测试代码:
func TestSendAwait(t *testing.T) {
m := "Hello World"
go func() {
conn, err := net.Dial("tcp", testingAddr)
if err != nil {
t.Fatal(err)
}
defer conn.Close()
t.Log("client connected to server") // DEBUG
conn.SetDeadline(time.Now().Add(2 * time.Second))
conn.Write([]byte(m))
conn.SetDeadline(time.Now().Add(2 * time.Second))
buf, err := ioutil.ReadAll(conn)
if err != nil {
t.Fatal(err)
}
t.Log(string(buf))
}()
ln, err := net.Listen("tcp", testingAddr)
if err != nil {
t.Fatal(err)
}
defer ln.Close()
t.Log("server started") // DEBUG
conn, err := ln.Accept()
if err != nil {
t.Fatal(err)
}
defer conn.Close()
t.Log("server received connection") // DEBUG
buf, err := ioutil.ReadAll(conn)
if err != nil {
t.Fatal(err)
}
t.Logf("server read buffer: %v", buf) // DEBUG
_, err = conn.Write(buf)
if err != nil {
t.Fatal(err)
}
t.Log("server wrote to connection") // DEBUG
}
在连接上设置了最后期限,否则死锁将是无限期的。输出如下:
transmission_test.go:42: server started
transmission_test.go:24: client connected to server
transmission_test.go:49: server received connection
transmission_test.go:32: read tcp 127.0.0.1:41164->127.0.0.1:9090: i/o timeout
transmission_test.go:55: server read buffer: [72 101 108 108 111 32 87 111 114 108 100]
transmission_test.go:61: server wrote to connection
Process finished with exit code 1
我不明白为什么客户端无法读取并退出,然后服务器才决定通过套接字发送数据?即使我增加客户端中的读取期限也会发生这种情况。
【问题讨论】:
-
我开始怀疑这是因为客户端没有通知服务器它发送的消息已经结束。我不知道如何去测试这个理论。一个线程建议在消息中添加换行符,但没有奏效。
标签: go networking server client deadlock