【发布时间】:2020-05-06 18:11:17
【问题描述】:
对于 tcp 服务器,我们经常使用 Listen() 和 Accept()。
func main() {
ln, err := net.Listen("tcp", ":6000")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
for {
conn, err := ln.Accept()
if err != nil {
fmt.Println(err)
continue
}
go handleConnection(conn)
}
}
但是有两种方法可以处理 Accept 返回的连接:
1
func handleConnection(c net.Conn) {
buf := make([]byte, 4096)
for {
n, err := c.Read(buf)
if err != nil || n == 0 {
c.Close()
break
}
n, err = c.Write(buf[0:n])
if err != nil {
c.Close()
break
}
}
fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
}
2
func handleConnection(c net.Conn) {
defer c.Close()
buf := make([]byte, 4096)
n, err := c.Read(buf)
if err != nil || n == 0 {
c.Close()
break
}
n, err = c.Write(buf[0:n])
if err != nil {
c.Close()
break
}
fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
}
这两种方法是否正确?似乎方法 1 重用了连接。但是如何向客户端指示EOF?
【问题讨论】:
-
使用
io.Copy(c, c)来解决这个问题。关闭连接以指示 EOF。 (1&2) 读取可以返回数据和错误。在处理错误之前写入数据。 (2) 该程序可能不会从连接中读取所有数据。 -
旁注:在代码部分 2 中,您有一个
defer c.Close(),因此从handleConnection返回(或恐慌)将调用c.Close()。这意味着您不需要剩余的c.Close()调用。
标签: go tcp connection tcpserver