part5.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // Solution to part 5 of the Whispering Gophers code lab.
  2. //
  3. // This program extends part 4.
  4. //
  5. // It listens on an available public IP and port, and for each incoming
  6. // connection it decodes JSON-encoded messages and writes them to standard
  7. // output.
  8. // It simultaneously makes a connection to the host and port specified by -peer,
  9. // reads lines from standard input, and writes JSON-encoded messages to the
  10. // network connection.
  11. // The messages include the listen address. For example:
  12. // {"Addr": "127.0.0.1:41232", "Body": "Hello"!}
  13. //
  14. // You can test this program by listening with the dump program:
  15. // $ dump -listen=localhost:8000
  16. // In another terminal, running this program:
  17. // $ part5 -peer=localhost:8000
  18. // And in a third terminal, running part2 with the address printed by part5:
  19. // $ part2 -dial=192.168.1.200:54312
  20. // Lines typed in the third terminal should appear in the second, and those
  21. // typed in the second window should appear in the first.
  22. //
  23. package main
  24. import (
  25. "bufio"
  26. "encoding/json"
  27. "flag"
  28. "fmt"
  29. "log"
  30. "net"
  31. "os"
  32. "code.google.com/p/whispering-gophers/util"
  33. )
  34. var (
  35. peerAddr = flag.String("peer", "", "peer host:port")
  36. self string
  37. )
  38. type Message struct {
  39. Addr string
  40. Body string
  41. }
  42. func main() {
  43. flag.Parse()
  44. // TODO: Create a new listener using util.Listen and put it in a variable named l.
  45. l, err := util.Listen()
  46. if err != nil {
  47. log.Fatal("Listen error: ", err)
  48. }
  49. // TODO: Set the global variable self with the address of the listener.
  50. self = l.Addr().String()
  51. // TODO: Print the address to the standard output
  52. fmt.Printf("Listening on %s\n", self)
  53. go dial(*peerAddr)
  54. for {
  55. c, err := l.Accept()
  56. if err != nil {
  57. log.Fatal(err)
  58. }
  59. go serve(c)
  60. }
  61. }
  62. func serve(c net.Conn) {
  63. defer c.Close()
  64. d := json.NewDecoder(c)
  65. for {
  66. var m Message
  67. err := d.Decode(&m)
  68. if err != nil {
  69. log.Println(err)
  70. return
  71. }
  72. fmt.Printf("%#v\n", m)
  73. }
  74. }
  75. func dial(addr string) {
  76. c, err := net.Dial("tcp", addr)
  77. if err != nil {
  78. log.Fatal(err)
  79. }
  80. s := bufio.NewScanner(os.Stdin)
  81. e := json.NewEncoder(c)
  82. for s.Scan() {
  83. m := Message{
  84. // TODO: Put the self variable in the new Addr field.
  85. Addr: self,
  86. Body: s.Text(),
  87. }
  88. err := e.Encode(m)
  89. if err != nil {
  90. log.Fatal(err)
  91. }
  92. }
  93. if err := s.Err(); err != nil {
  94. log.Fatal(err)
  95. }
  96. }