Exercise 8.8: Use select to modify the echo server in Section 8.3 to add a timeout so that the server automatically disconnects when the client does not have any calls for 10 seconds.
reverb3.go
package main import ( "bufio" "fmt" "log" "net" "strings" "sync" "time" ) func main() { listener, err := net.Listen("tcp", ":8040") if err != nil { log.Fatal(err) } for { conn, err := listener.Accept() if err != nil { log.Print(err) // e.g., connection aborted continue } go handleConn(conn) //Create new goroutines to handle the connection } } /* 1. Start a goroutine, for infinite loop so that it cannot be interrupted The select statement case judges two channels One is to disconnect after 10 seconds The other is the channel sent after receiving the standard input. After receiving the value, start the goroutine output 2. The for loop receives the standard input and sends it to the channel of the message after receiving it */ func handleConn(c net.Conn) { input := bufio.NewScanner(c) var wg sync.WaitGroup var message = make(chan string) wg.Add(1) go func() { defer wg.Done() for { select { case <-time.After(10 * time.Second): c.Close() case mes := <-message: wg.Add(1) go func(c net.Conn, shout string, delay time.Duration) { defer wg.Done() fmt.Fprintln(c, "\t", strings.ToUpper(shout)) time.Sleep(delay) fmt.Fprintln(c, "\t", shout) time.Sleep(delay) fmt.Fprintln(c, "\t", strings.ToLower(shout)) //ch<-struct{}{} }(c, mes, 1*time.Second) } } }() for input.Scan() { text := input.Text() message <- text } wg.Wait() //cw := c.(*net.TCPConn) //cw.CloseWrite() c.Close() }