我正在深入研究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客户端后,服务器甚至不会打印出messeage长度(5)和消息(“Hello”)。如果我在客户端注释掉读取和打印,那么事情就会顺利进行。
我尝试用谷歌搜索答案,但什么都没有出现。
我做错了什么?我在客户端使用conn.Read()错了吗?
修改
我实际上可以访问Linux,所以这里是相关功能的SIGQUIT转储。
服务器
客户端
答案 0 :(得分:2)
for {
n, err := c.Read(buffer)
totalBytes += n
if err != nil {
if err != io.EOF {
log.Printf("Read error: %s", err)
}
break
}
}
这是因为您正在读取连接直到发生EOF错误
conn.Write([]byte("Hello"))
在您实际关闭连接之前,上述声明根本不会达到EOF
在按ctrl + c客户端时,连接将被关闭,因此EOF发生在服务器端,这就是为什么它退出服务器端进行循环并打印这些
的原因127.0.0.1:****
Hello
Replied
如果你想做这项工作,你不应该阅读连接直到EOF
还有很多其他选择