main.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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.osinet.fr/fgm/whispering_gophers/util"
  33. )
  34. var (
  35. listenAddr = flag.String("listen", "", "peer host:port")
  36. peerAddr = flag.String("peer", "", "peer host:port")
  37. self string
  38. )
  39. type Message struct {
  40. Addr string
  41. Body string
  42. }
  43. func main() {
  44. flag.Parse()
  45. var l net.Listener
  46. var err error
  47. // Create a new listener using util.Listen and put it in a variable named l.
  48. if *listenAddr == "" {
  49. l, err = util.ListenOnFirstUsableInterface()
  50. } else {
  51. l, err = net.Listen("tcp4", *listenAddr)
  52. }
  53. if err != nil {
  54. log.Fatal(err)
  55. }
  56. // Set the global variable self with the address of the listener.
  57. self = l.Addr().String()
  58. // Print the address to the standard output
  59. fmt.Printf("Listening on %s\", ", self)
  60. go dial(*peerAddr)
  61. for {
  62. c, err := l.Accept()
  63. if err != nil {
  64. log.Fatal(err)
  65. }
  66. go serve(c)
  67. }
  68. }
  69. func serve(c net.Conn) {
  70. defer c.Close()
  71. d := json.NewDecoder(c)
  72. for {
  73. var m Message
  74. err := d.Decode(&m)
  75. if err != nil {
  76. log.Println(err)
  77. return
  78. }
  79. fmt.Printf("%#v\n", m)
  80. }
  81. }
  82. func dial(addr string) {
  83. c, err := net.Dial("tcp", addr)
  84. if err != nil {
  85. log.Fatal(err)
  86. }
  87. s := bufio.NewScanner(os.Stdin)
  88. e := json.NewEncoder(c)
  89. for s.Scan() {
  90. m := Message{
  91. // Put the self variable in the new Addr field.
  92. Addr: self,
  93. Body: s.Text(),
  94. }
  95. err := e.Encode(m)
  96. if err != nil {
  97. log.Fatal(err)
  98. }
  99. }
  100. if err := s.Err(); err != nil {
  101. log.Fatal(err)
  102. }
  103. os.Exit(0)
  104. }