package main import ( "bufio" "fmt" "log" "net" "time" ) type client struct { _chan chan <- string name string } var ( entering = make(chan client) leaving = make(chan client) messages = make(chan string) cancel = make(chan time.Time) ) func handleConn(conn net.Conn) { defer conn.Close() ch := make(chan string) go clientWriter(conn,ch) who := conn.RemoteAddr().String() client := client{ _chan: ch, name: who, } ch <- "You " + who messages <- who + " connected" entering <- client inputChan := make(chan string) timeout := time.NewTimer(40*time.Second) defer timeout.Stop() input := bufio.NewScanner(conn) go func() { log.Println("inside of goroutine") for input.Scan() { log.Println("inside of Scan for loop") inputChan <- client.name + ": " + input.Text() } if err := input.Err(); err != nil { log.Printf("Scanner error: %v", err) } else { log.Println("Scanner reached EOF (connection closed)") } log.Println("Closing input channel") close(inputChan) }() loop: for { select { case text,ok := <- inputChan: if !ok { leaving <- client messages <- who + " disconnected" break loop } if !timeout.Stop() { <- timeout.C } timeout.Reset(40*time.Second) messages <- text case <- timeout.C: ch <- "Connection timed out due to inactivity" leaving <- client messages <- who + " disconnected (timeout)" break loop } } } func clientWriter(conn net.Conn, ch <- chan string) { for msg := range ch { fmt.Fprintln(conn,msg) } } func broadcaster() { clients := make(map[client]bool) for { select { case msg := <- messages: log.Println("Got a msg") for cli := range clients { cli._chan <- msg } case cli := <- entering: cli._chan <- "List of connected clients" for i := range clients { cli._chan <- i.name } clients[cli] = true case cli := <- leaving: log.Printf("Deleting client %s") delete(clients,cli) close(cli._chan) } } } func main() { listener,err := net.Listen("tcp",":9090") if err != nil { log.Fatalf("Error in Lister %v",err) } go broadcaster() for { conn,err := listener.Accept() if err != nil { log.Fatalf("Error in Accept %v",err) continue } go handleConn(conn) } }