英文:
Two way connections in Go
问题
我正在尝试使用Go语言制作一个简单的控制台聊天程序,只是为了练习。然而,我不知道如何从服务器发送消息回来。服务器只接收消息然后关闭连接。我该如何发送响应呢?
我已经搜索到了关于WebSockets的信息,但我认为它们是用于与浏览器进行交互的。
这是服务器的两个函数:
func runServer() {
// 监听端口
listen, error := net.Listen("tcp", ":8272")
// 处理可能的错误
if error != nil {
fmt.Println(error)
return
}
fmt.Println("正在监听端口 8272.")
for {
// 接受连接
con, error := listen.Accept()
// 处理可能的错误
if error != nil {
fmt.Println(error)
continue
}
fmt.Println("连接已接受.")
// 处理连接
go handleConnection(con)
}
}
func handleConnection(con net.Conn) {
fmt.Println("处理连接.")
var message string
// 解码接收到的消息
decoder := gob.NewDecoder(con)
error := decoder.Decode(&message)
// 检查错误
if error != nil {
fmt.Println(error)
} else {
fmt.Println("接收到消息:", message)
}
// 关闭连接
con.Close()
fmt.Println("连接已关闭.")
}
这是客户端的函数:
func runClient() {
// 连接服务器
con, error := net.Dial("tcp", "127.0.0.1:8272")
// 处理可能的错误
if error != nil {
fmt.Println(error)
return
}
fmt.Println("已连接到 127.0.0.1:8272.")
// 发送消息
message := "Hello world"
encoder := gob.NewEncoder(con)
error = encoder.Encode(message)
// 检查错误
if error != nil {
fmt.Println(error)
}
con.Close()
fmt.Println("消息已发送。连接已关闭.")
}
希望能对你有所帮助。
英文:
I am trying to make a simple console chat in Go, just to practice. However, I don't know how to send messages back from the server. The server just receives a message and then closes the connection. How could I send a response?
I have been searching and found information about websockets, but I think that they are used to interact with browsers.
This are the two functions of the server:
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.")
}
This is the function of the client:
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.")
}
Thanks in advance.
答案1
得分: 4
您的con
对象是一个连接,其中包含了Read
和Write
方法,可以在这里找到详细描述:这里。您应该在连接上循环,尝试Read
传入的数据,然后处理它并(可能)Write
回服务器的响应。(在这里,bufferio
包等可以帮助您以更方便的方式处理数据,这只是底层的ReadWriter
接口)
文档中展示了一个简单的示例:
go func(c net.Conn) {
// 回显所有传入的数据。
io.Copy(c, c)
// 关闭连接。
c.Close()
}(conn)
该示例只处理第一条消息,然后关闭连接。您可以像这样处理每条传入的消息:
go func(c net.Conn) {
// 无限循环:获取数据,复制它们,然后重新开始
for {
// 回显所有传入的数据。
io.Copy(c, c)
}
// 关闭连接。
c.Close()
}(conn)
当然,您可以根据您的服务器将io.Copy
替换为相应的处理逻辑,所以您的示例可能是这样的:
func handleConnection(con net.Conn) {
fmt.Println("处理连接。")
defer func() {
// 关闭连接
con.Close()
fmt.Println("连接已关闭。")
}()
var message string
// 解码接收到的消息
decoder := gob.NewDecoder(con)
encoder := gob.NewEncoder(con)
for {
error := decoder.Decode(&message)
// 检查错误
if error != nil {
fmt.Println(error)
// 退出循环
return
} else {
fmt.Println("接收到:", message)
// 发送回复
if error = encoder.Encode(message); error != nil {
fmt.Println(error)
return
} else {
fmt.Println("回显成功!等待下一条消息...")
}
}
}
}
此外,您可能应该在日志消息中使用log
包而不是fmt
包(但这在这里并不重要)。
了解它是如何工作的一个好方法是浏览默认的http
服务器的实现代码这里。
类似地,您的客户端应该使用相同的模式进行循环:
LOOP:
发送数据(例如 encoder.Encode)
接收数据(例如 decoder.Decode)
如果有问题或终止 -> 退出循环
END
关闭连接
英文:
Your con
object is a connection, which has Read
and Write
methods described here: here. You should loop on the connection, trying to Read
incoming data, then process it and (possibly) Write
back the server response. (Here, bufferio
package and the like can help you process it in a more convenient way, this is just the low-level ReadWriter
interface)
The documentation shows a tiny example:
go func(c net.Conn) {
// Echo all incoming data.
io.Copy(c, c)
// Shut down the connection.
c.Close()
}(conn)
Which processes only the first message and then closes. You can process each incoming message like this:
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)
Replacing io.Copy
with whatever is relevant to your server of course, so your example would be something like this:
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...")
}
}
}
}
Also, you should probably use package log
instead of fmt
for your logging messages (but this is irrelevant here).
A good place to understand how it all works is to browse the implementation of the default http
server here.
Similarly, your client should loop using the same pattern:
LOOP:
Send data (e.g. encoder.Encode)
Receive data (e.g. decoder.Decode)
if problem or termination -> break out of loop
END
close connection
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论