part4.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // Solution to part 4 of the Whispering Gophers code lab.
  2. //
  3. // This program is a combination of parts 2 and 3.
  4. //
  5. // It listens on the host and port specified by the -listen flag.
  6. // For each incoming connection, it launches a goroutine that reads and decodes
  7. // JSON-encoded messages from the connection and prints them to standard
  8. // output.
  9. // It concurrently makes a connection the host and port specified by the -dial
  10. // flag, reads lines from standard input, and writes JSON-encoded messages to
  11. // the network connection.
  12. //
  13. // You can test it by running part3 in one terminal:
  14. // $ part3 -listen=localhost:8000
  15. // Running this program in another terminal:
  16. // $ part4 -listen=localhost:8001 -dial=localhost:8000
  17. // And running part2 in another terminal:
  18. // $ part2 -dial=localhost:8001
  19. // Lines typed in the second terminal should appear as JSON objects in the
  20. // first terminal, and those typed at the third terminal should appear in the
  21. // second.
  22. //
  23. package main
  24. import (
  25. "encoding/json"
  26. "flag"
  27. "fmt"
  28. "log"
  29. "net"
  30. "bufio"
  31. "os"
  32. )
  33. var (
  34. listenAddr = flag.String("listen", "", "host:port to listen on")
  35. dialAddr = flag.String("dial", "", "host:port to dial")
  36. )
  37. type Message struct {
  38. Body string
  39. }
  40. func main() {
  41. flag.Parse()
  42. // TODO: Launch dial in a new goroutine, passing in *dialAddr.
  43. go dial(*dialAddr)
  44. l, err := net.Listen("tcp", *listenAddr)
  45. if err != nil {
  46. log.Fatal("Listen error: ", err)
  47. }
  48. for {
  49. c, err := l.Accept()
  50. if err != nil {
  51. log.Fatal("Accept error: ", err)
  52. }
  53. go serve(c)
  54. }
  55. }
  56. func serve(c net.Conn) {
  57. defer c.Close()
  58. d := json.NewDecoder(c)
  59. for {
  60. var m Message
  61. err := d.Decode(&m)
  62. if err != nil {
  63. log.Println(err)
  64. return
  65. }
  66. fmt.Printf("%#v\n", m)
  67. }
  68. }
  69. func dial(addr string) {
  70. // TODO: put the contents of the main function from part 2 here.
  71. c, err := net.Dial("tcp", addr)
  72. if err != nil {
  73. log.Fatal("Dial error: ", err)
  74. }
  75. s := bufio.NewScanner(os.Stdin)
  76. e := json.NewEncoder(c)
  77. for s.Scan() {
  78. m := Message{Body: s.Text()}
  79. err := e.Encode(m)
  80. if err != nil {
  81. log.Fatal("Encoding error: ", err)
  82. }
  83. }
  84. if err := s.Err(); err != nil {
  85. log.Fatal("Scan error: ", err)
  86. }
  87. }