Go: Reversing TCP Server
Implement a TCP server that accepts messages in the form of a string. Reverse the messages and return them to the client.
The stub function accepts an array of strings, messages, runs the server, waits for it to be ready, then sends the messages one by one to the server and prints responses. The server address is given in the constant address along with maxBufferSize for reading/writing purposes.
Example
messages= [“adi”, “glm”, “tuv”]
The TCP server should respond with [“ida”,”mlg”,”vut”].
Function Description
Complete the function TCPServer in the editor below.
TCPServer has the following parameter:
bool ready: a channel that indicates whether the server is ready
Returns
None: all responses should be read from the TCP connection initiated by a TCP client
Constraints
- The total number of messages does not exceed 500.
- Each message contains a maximum of 1000 lower case English letters only.
SOLUTION:
package main
import (
"bufio"
"fmt"
"io"
"net"
"os"
"strconv"
"strings"
)
/*
* Complete the 'TCPServer' function below.
*
* The function accepts chan bool ready as a parameter.
*/
func TCPServer(ready chan bool) {
ln, err := net.Listen("tcp", address)
if err != nil {
panic(err)
}
defer ln.Close()
ready <- true
for {
conn, err := ln.Accept()
if err != nil {
continue
}
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
defer conn.Close()
buffer := make([]byte, maxBufferSize)
n, err := conn.Read(buffer)
if err != nil {
return
}
message := string(buffer[:n])
reversed := reverseString(message)
conn.Write([]byte(reversed))
}
func reverseString(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
const maxBufferSize = 1024
const address = "127.0.0.1:3333"
func main() {
stdout, err := os.Create(os.Getenv("OUTPUT_PATH"))
checkError(err)
defer stdout.Close()
reader := bufio.NewReaderSize(os.Stdin, 16*1024*1024)
writer := bufio.NewWriterSize(stdout, 16*1024*1024)
messagesCount, err := strconv.ParseInt(strings.TrimSpace(readLine(reader)), 10, 64)
checkError(err)
var messages []string
for i := 0; i < int(messagesCount); i++ {
messagesItem := readLine(reader)
messages = append(messages, messagesItem)
}
ready := make(chan bool)
go TCPServer(ready)
<-ready
reversed, err := tcpClient(messages)
if err != nil {
panic(err)
}
for _, msg := range reversed {
fmt.Fprintf(writer, "%s\n", msg)
}
writer.Flush()
}
func readLine(reader *bufio.Reader) string {
str, _, err := reader.ReadLine()
if err == io.EOF {
return ""
}
return strings.TrimRight(string(str), "\r\n")
}
func checkError(err error) {
if err != nil {
panic(err)
}
}
func tcpClient(messages []string) ([]string, error) {
tcpAddr, err := net.ResolveTCPAddr("tcp", address)
if err != nil {
return []string{}, err
}
reversed := []string{}
for _, msg := range messages {
conn, err := net.DialTCP("tcp", nil, tcpAddr)
if err != nil {
return []string{}, err
}
_, err = conn.Write([]byte(msg))
if err != nil {
return []string{}, err
}
reply := make([]byte, maxBufferSize)
n, err := conn.Read(reply)
if err != nil {
return []string{}, err
}
reversed = append(reversed, string(reply[:n]))
conn.Close()
}
return reversed, nil
}