Reputation: 6256
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.
Upvotes: 0
Views: 3568
Reputation: 8689
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
Upvotes: 4