我正在尝试在Go中进行简单的控制台聊天,只是为了练习。但是,我不知道如何从服务器发回消息。服务器只接收一条消息,然后关闭连接。我怎么能发送回复?
我一直在搜索并找到有关websockets的信息,但我认为它们用于与浏览器进行交互。
这是服务器的两个功能:
func runServer() {
// Listen on a port
listen, error := net.Listen("tcp", ":8272")
// Handles eventual errors
if error != nil {
fmt.Println(error)
return
}
fmt.Println("Listening in port 8272.")
for {
// Accepts connections
con, error := listen.Accept()
// Handles eventual errors
if error != nil {
fmt.Println(error)
continue
}
fmt.Println("Connection accepted.")
// Handles the connection
go handleConnection(con)
}
}
func handleConnection(con net.Conn) {
fmt.Println("Handling connection.")
var message string
// Decodes the received message
decoder := gob.NewDecoder(con)
error := decoder.Decode(&message)
// Checks for errors
if error != nil {
fmt.Println(error)
} else {
fmt.Println("Received", message)
}
// Closes the connection
con.Close()
fmt.Println("Connection closed.")
}
这是客户的功能:
func runClient() {
// Connects to server
con, error := net.Dial("tcp", "127.0.0.1:8272")
// Handles eventual errors
if error != nil {
fmt.Println(error)
return
}
fmt.Println("Connected to 127.0.0.1:8272.")
// Sends a message
message := "Hello world"
encoder := gob.NewEncoder(con)
error = encoder.Encode(message)
// Checks for errors
if error != nil {
fmt.Println(error)
}
con.Close()
fmt.Println("Message sent. Connection closed.")
}
提前致谢。
答案 0 :(得分:3)
您的con
对象是一种连接,其中包含Read
和Write
方法:here。您应该循环连接,尝试Read
传入数据,然后处理它并(可能)Write
返回服务器响应。 (这里,bufferio
包等可以帮助您以更方便的方式处理它,这只是低级ReadWriter
接口)
文档显示了一个小example:
go func(c net.Conn) {
// Echo all incoming data.
io.Copy(c, c)
// Shut down the connection.
c.Close()
}(conn)
仅处理第一条消息,然后关闭。您可以像这样处理每个传入的消息:
go func(c net.Conn) {
// Infinite loop: Get data, copy them and start over
for {
// Echo all incoming data.
io.Copy(c, c)
}
// Shut down the connection.
c.Close()
}(conn)
当使用与您的服务器相关的任何内容替换io.Copy
时,您的示例将是这样的:
func handleConnection(con net.Conn) {
fmt.Println("Handling connection.")
defer func() {
// Closes the connection
con.Close()
fmt.Println("Connection closed.")
}()
var message string
// Decodes the received message
decoder := gob.NewDecoder(con)
encoder := gob.NewEncoder(con)
for {
error := decoder.Decode(&message)
// Checks for errors
if error != nil {
fmt.Println(error)
// Exit the loop
return
} else {
fmt.Println("Received", message)
// Sending back
if error = encoder.Encode(message); error != nil {
fmt.Println(error)
return
} else {
fmt.Println("Echo'd successfuly ! Waiting for next message...")
}
}
}
}
此外,您应该使用程序包log
而不是fmt
来记录日志消息(但这与此无关)。
理解这一切是如何工作的好地方是浏览默认http
服务器here的实现。
同样,您的客户端应使用相同的模式循环:
LOOP:
Send data (e.g. encoder.Encode)
Receive data (e.g. decoder.Decode)
if problem or termination -> break out of loop
END
close connection