Skip to content

Instantly share code, notes, and snippets.

@fourcube
Last active August 29, 2015 14:20
Show Gist options
  • Save fourcube/2f6b29edcf600743a9dd to your computer and use it in GitHub Desktop.
Save fourcube/2f6b29edcf600743a9dd to your computer and use it in GitHub Desktop.
Go Echo Server
package main
import (
"io"
"log"
"net"
)
func EchoServer(addr string, done chan struct{}) net.Listener {
listener, err := net.Listen("tcp", addr)
if err != nil {
log.Fatalf("Error listening, %v ", err)
}
// This implementation does not block, but instead runs it's
// accept -> handle loop inside a goroutine
go func() {
for {
select {
// When the 'done' channel gets closed or receives
// the echo server's listener gets shut down
case <-done:
listener.Close()
return
default:
conn, err := listener.Accept()
if err != nil {
log.Printf("Error during accept, %v ", err)
return
}
// Do all the work inside a goroutine so we can quickly accept
// other connections
go handle(conn)
}
}
}()
return listener
}
func handle(client net.Conn) {
var err error
for err == nil {
// ...simply return everything the client sends to itself
_, err = io.Copy(client, client)
if err != nil && err != io.EOF {
log.Printf("Error during echo %v", err)
}
}
}
package main
import (
"net"
"testing"
)
func TestEchoServer(t *testing.T) {
done := make(chan struct{})
echo := echoServer(":0", done)
conn, err := net.Dial("tcp", echo.Addr().String())
if err != nil {
t.Errorf("Expected no error, got %v", err)
}
recv := make([]byte, 32)
conn.Write([]byte("foo"))
n, err := conn.Read(recv)
if err != nil {
t.Errorf("Expected no error, got %v", err)
}
data := string(recv[:n])
if data != "foo" {
t.Errorf("Expected to receive 'foo', got %s", data)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment