package main import ( "bufio" "io" "log" "net" "time" ) // read all messages from client. func read(rc io.ReadCloser, id int, msg chan<- string, done chan<- int) { defer rc.Close() scanner := bufio.NewScanner(rc) for scanner.Scan() { msg <- scanner.Text() } done <- id } // write 'tick' message to all clients. func write(conns []net.Conn) { for _, c := range conns { if c != nil { io.WriteString(c, "tick\n") } } } // add a client and read messages if there is room. func addClient(conns []net.Conn, conn net.Conn, msg chan<- string, done chan<- int) []net.Conn { for i, c := range conns { if c == nil { go read(conn, i, msg, done) conns[i] = conn return conns } } // reject the client if we are full conn.Close() return conns } func main() { conns := make([]net.Conn, 15) connC := make(chan net.Conn, 0) msgC := make(chan string, 0) doneC := make(chan int, 0) listener, err := net.Listen("tcp", ":8080") if err != nil { log.Fatalf("listening on :8080: %s", err.Error()) } go func() { for { c, err := listener.Accept() if err == nil { connC <- c } } }() ticker := time.NewTicker(time.Second) for { select { case conn := <-connC: conns = addClient(conns, conn, msgC, doneC) case id := <-doneC: conns[id] = nil case msg := <-msgC: log.Printf("client said: %s", msg) case <-ticker.C: write(conns) } } }