Go 如何使用网络连接读取方法保持读取
我正在创建一个简单的聊天服务器,作为一个个人项目来学习网络包和围棋中的一些并发性。我的第一个想法是让服务器使用nc命令Go 如何使用网络连接读取方法保持读取,go,Go,我正在创建一个简单的聊天服务器,作为一个个人项目来学习网络包和围棋中的一些并发性。我的第一个想法是让服务器使用nc命令echo-n“hello”| nc-w1-4 localhost 2016-p 61865打印发送的任何内容。但是,在第一次读取后,我的代码将忽略后续消息 func (s *Server) messageReader(conn net.Conn) { defer conn.Close() buffer := make([]byte, 1024) for { //read
echo-n“hello”| nc-w1-4 localhost 2016-p 61865打印发送的任何内容。但是,在第一次读取后,我的代码将忽略后续消息
func (s *Server) messageReader(conn net.Conn) {
defer conn.Close()
buffer := make([]byte, 1024)
for {
//read buff
blen, err := conn.Read(buffer)
if err != nil {
log.Fatal(err)
}
message := string(buffer[:blen])
if message == "/quit" {
fmt.Println("quit command received. Bye.")
return
}
if blen > 0 {
fmt.Println(message)
buffer = buffer[:0]
}
}
}
// Run Start up the server. Manages join and leave chat
func (s *Server) Run() {
// Listen on port TCP 2016
listener, err := net.Listen("tcp", ":2016")
if err != nil {
log.Fatal(err)
}
defer listener.Close()
for {
//wait for connection
conn, err := listener.Accept()
if err != nil {
log.Fatal(err)
}
go s.messageReader(conn)
}
}
如果我从一个新客户机发送一条新消息,它会毫无问题地打印出来,但如果我发送另一条消息,它什么也不会做。我遗漏了什么?我需要重置Conn还是关闭它并生成一个新的Conn?打印消息后,将缓冲区
切成零长度。无法将任何数据读入零长度切片。根本没有理由对读取缓冲区进行重新切片
您还需要在检查错误之前处理读取的字节,因为成功读取时可以返回io.EOF
您不应该在服务器的读取循环中使用log.Fatal
,因为这会调用os.Exit
正在工作的messageReader
正文可能如下所示:
defer conn.Close()
buffer := make([]byte, 1024)
for {
n, err := conn.Read(buffer)
message := string(buffer[:n])
if message == "/quit" {
fmt.Println("quit command received. Bye.")
return
}
if n > 0 {
fmt.Println(message)
}
if err != nil {
log.Println(err)
return
}
}
不过,您应该注意,因为这里没有使用任何类型的帧协议,所以不能保证每个conn.Read
都返回完整或单个消息。您需要某种更高级的协议来界定流中的消息 在打印消息后,将缓冲区切成零长度。无法将任何数据读入零长度切片。根本没有理由对读取缓冲区进行重新切片
您还需要在检查错误之前处理读取的字节,因为成功读取时可以返回io.EOF
您不应该在服务器的读取循环中使用log.Fatal
,因为这会调用os.Exit
正在工作的messageReader
正文可能如下所示:
defer conn.Close()
buffer := make([]byte, 1024)
for {
n, err := conn.Read(buffer)
message := string(buffer[:n])
if message == "/quit" {
fmt.Println("quit command received. Bye.")
return
}
if n > 0 {
fmt.Println(message)
}
if err != nil {
log.Println(err)
return
}
}
不过,您应该注意,因为这里没有使用任何类型的帧协议,所以不能保证每个conn.Read
都返回完整或单个消息。您需要某种更高级的协议来界定流中的消息 您建议在标准库中使用什么协议net/http
可以工作,但如果我没有弄错的话,http不是消息传递协议。我试图保持小范围,但我也想知道可以做什么或如何做。谢谢你回答中的额外内容。非常有用的知识。@cmejia:协议取决于您的需要。最常见的框架方法可能是简单的长度前缀字符串。您还可以设置一个分隔符,确保它不会出现在邮件中。包含点编码格式,使用\r\n
分隔行,使用\r\n
表示消息结束,以及MIME格式键值。您建议在标准库中使用什么协议net/http
可以工作,但如果我没有弄错的话,http不是消息传递协议。我试图保持小范围,但我也想知道可以做什么或如何做。谢谢你回答中的额外内容。非常有用的知识。@cmejia:协议取决于您的需要。最常见的框架方法可能是简单的长度前缀字符串。您还可以设置一个分隔符,确保它不会出现在邮件中。包含点编码格式,使用\r\n
分隔行,使用\r\n
表示消息结束,以及MIME格式键值。