【发布时间】:2016-12-03 10:15:50
【问题描述】:
我正在深入研究 Go 的网络方面,我想我会从 TCP 客户端和服务器开始。
我能够让客户端连接到服务器并成功发送一条简单的消息(“Hello”)。但是,我无法让服务器发回响应(或让客户端读取响应)。
这里是代码。
服务器
Address := "localhost:9999"
Addr, err := net.ResolveTCPAddr("tcp", Address)
if err != nil {
log.Fatal(err)
}
listener, err := net.ListenTCP("tcp", Addr)
if err != nil {
log.Fatal(err)
}
defer listener.Close()
//server loop
for {
conn, err := listener.Accept()
if err != nil {
continue
}
go handle(conn)
}
func handle(c net.Conn) {
totalBytes, message := connRead(c)
fmt.Println(c.RemoteAddr())
fmt.Println(string(message[:totalBytes]))
c.Write([]byte("Hi"))
fmt.Println("Replied")
c.Close()
}
func connRead(c net.Conn) (int, []byte) {
buffer := make([]byte, 4096)
totalBytes := 0
for {
n, err := c.Read(buffer)
totalBytes += n
if err != nil {
if err != io.EOF {
log.Printf("Read error: %s", err)
}
break
}
}
return totalBytes, buffer
}
客户
tcpAddr, err := net.ResolveTCPAddr("tcp", "localhost:9999")
if err != nil {
log.Fatal(err)
}
conn, err := net.DialTCP("tcp", nil, tcpAddr)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
_, err = conn.Write([]byte("Hello"))
if err != nil {
log.Fatal(err)
}
tBytes, resp := connRead(conn)
fmt.Println(tBytes)
fmt.Println(string(resp[:tBytes]))
func connRead(c net.Conn) (int, []byte) {
buffer := make([]byte, 4096)
totalBytes := 0
for {
fmt.Println("Stuck?")
n, err := c.Read(buffer)
fmt.Println("Stuck.")
totalBytes += n
fmt.Println(totalBytes)
if err != nil {
if err != io.EOF {
log.Printf("Read error: %s", err)
}
break
}
}
return totalBytes, buffer
}
据我所知,这不是服务器的问题。当我运行客户端时,一切都在fmt.Println("Stuck?") 之后停止。这让我相信它在某种程度上搞砸了n, err := c.Read(buffer) 声明。在我 Ctrl-C 客户端之前,服务器甚至不会打印出消息长度(5)和消息(“Hello”)。如果我在客户端注释掉读取和打印,那么事情就会顺利进行。
我尝试在谷歌上搜索答案,但没有任何结果。
我做错了什么?我在客户端中使用 conn.Read() 错误吗?
编辑:
我确实可以访问 Linux,所以这里是相关功能的 SIGQUIT 转储。
服务器
客户
【问题讨论】:
-
一目了然,它看起来像是客户端和服务器阻止读取连接上的 EOF。向正在运行的应用程序发送 SIQUIT 以找出它们被阻止的位置。
-
我在 Win 7 上,它不支持 SIGQUIT。
-
两个程序在读取时都被阻止。一个或两个对等点应该close the write side 的连接以解除阻塞另一个对等点。或者,您可以添加消息框架并在阅读完整消息后停止阅读。
-
如果服务器不打印 msg 长度,你怎么知道它正在接收一些东西?是 connRead 还是 conn.Read?
标签: go tcp network-programming