Created
April 6, 2011 11:25
-
-
Save kybernetyk/905496 to your computer and use it in GitHub Desktop.
Concurrent Echo Server in GO (CHANNELS ARE THE WAR!)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"net" | |
"os" | |
"fmt" | |
"bufio" | |
"strings" | |
) | |
var ( | |
port = 1337 | |
banner = "> ISCH FICK DEINE MUDDA\n" | |
) | |
type BlogSession struct { | |
write_chan chan string | |
read_chan chan string | |
control_chan chan string | |
conn net.Conn | |
} | |
var master_chan = make(chan string, 1000) | |
func readline(b *bufio.Reader) (p []byte, err os.Error) { | |
if p, err = b.ReadSlice('\n'); err != nil { | |
return nil, err | |
} | |
var i int | |
for i = len(p); i > 0; i-- { | |
if c := p[i-1]; c != ' ' && c != '\r' && c != '\t' && c != '\n' { | |
break | |
} | |
} | |
return p[0:i], nil | |
} | |
func clientReader(session BlogSession) { | |
var line []byte | |
br := bufio.NewReader(session.conn) | |
for { | |
line, _ = readline(br) | |
s := string(line) | |
session.read_chan <- s | |
} | |
} | |
func clientWriter(session BlogSession) { | |
var err os.Error | |
for { | |
b := []byte(<-session.write_chan) | |
_, err = session.conn.Write(b) | |
if err != nil { | |
session.control_chan <- "disconnect" | |
} | |
} | |
} | |
func processUserInput(session BlogSession) { | |
for { | |
user_input := <-session.read_chan | |
fmt.Println("client input: ", user_input) | |
items := strings.Split(user_input, " ", -1) | |
if items[0] == "echo" { | |
if len(items) < 2 { | |
session.write_chan <- "syntax: echo <shit to echo>\n" | |
} else { | |
s := strings.Join(items[1:], " ") | |
session.write_chan <- s | |
session.write_chan <- "\n" | |
} | |
} | |
if items[0] == "quit" { | |
session.control_chan <- "disconnect" | |
} | |
if items[0] == "upload" && items[1] == "virus" { | |
master_chan <- "diediedie" | |
} | |
} | |
} | |
func handleClient(conn net.Conn) { | |
defer conn.Close() | |
session := BlogSession{} | |
session.write_chan = make(chan string, 1000) | |
session.read_chan = make(chan string, 1000) | |
session.control_chan = make(chan string, 1000) | |
session.conn = conn | |
go clientReader(session) | |
go clientWriter(session) | |
go processUserInput(session) | |
session.write_chan <- banner | |
for { | |
select { | |
case status := <-session.control_chan: | |
fmt.Println("control chan: ", status) | |
if status == "disconnect" { | |
return | |
} | |
} | |
} | |
} | |
func serverFunc() { | |
service := fmt.Sprintf(":%d", port) | |
tcpAddr, _ := net.ResolveTCPAddr(service) | |
listener, _ := net.ListenTCP("tcp", tcpAddr) | |
fmt.Println("listening on: " + tcpAddr.IP.String() + service) | |
for { | |
conn, err := listener.Accept() | |
if err != nil { | |
continue | |
} | |
go handleClient(conn) | |
} | |
} | |
func main() { | |
go serverFunc() | |
for { | |
select { | |
case command := <-master_chan: | |
if command == "diediedie" { | |
return | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment