123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- // Solution to part 5 of the Whispering Gophers code lab.
- //
- // This program extends part 4.
- //
- // It listens on an available public IP and port, and for each incoming
- // connection it decodes JSON-encoded messages and writes them to standard
- // output.
- // It simultaneously makes a connection to the host and port specified by -peer,
- // reads lines from standard input, and writes JSON-encoded messages to the
- // network connection.
- // The messages include the listen address. For example:
- // {"Addr": "127.0.0.1:41232", "Body": "Hello"!}
- //
- // You can test this program by listening with the dump program:
- // $ dump -listen=localhost:8000
- // In another terminal, running this program:
- // $ part5 -peer=localhost:8000
- // And in a third terminal, running part2 with the address printed by part5:
- // $ part2 -dial=192.168.1.200:54312
- // Lines typed in the third terminal should appear in the second, and those
- // typed in the second window should appear in the first.
- //
- package main
- import (
- "bufio"
- "encoding/json"
- "flag"
- "fmt"
- "log"
- "net"
- "os"
- "code.osinet.fr/fgm/whispering_gophers/util"
- )
- var (
- listenAddr = flag.String("listen", "", "peer host:port")
- peerAddr = flag.String("peer", "", "peer host:port")
- self string
- )
- type Message struct {
- Addr string
- Body string
- }
- func main() {
- flag.Parse()
- var l net.Listener
- var err error
- // Create a new listener using util.Listen and put it in a variable named l.
- if *listenAddr == "" {
- l, err = util.ListenOnFirstUsableInterface()
- } else {
- l, err = net.Listen("tcp4", *listenAddr)
- }
- if err != nil {
- log.Fatal(err)
- }
- // Set the global variable self with the address of the listener.
- self = l.Addr().String()
- // Print the address to the standard output
- fmt.Printf("Listening on %s\", ", self)
- go dial(*peerAddr)
- for {
- c, err := l.Accept()
- if err != nil {
- log.Fatal(err)
- }
- go serve(c)
- }
- }
- func serve(c net.Conn) {
- defer c.Close()
- d := json.NewDecoder(c)
- for {
- var m Message
- err := d.Decode(&m)
- if err != nil {
- log.Println(err)
- return
- }
- fmt.Printf("%#v\n", m)
- }
- }
- func dial(addr string) {
- c, err := net.Dial("tcp", addr)
- if err != nil {
- log.Fatal(err)
- }
- s := bufio.NewScanner(os.Stdin)
- e := json.NewEncoder(c)
- for s.Scan() {
- m := Message{
- // Put the self variable in the new Addr field.
- Addr: self,
- Body: s.Text(),
- }
- err := e.Encode(m)
- if err != nil {
- log.Fatal(err)
- }
- }
- if err := s.Err(); err != nil {
- log.Fatal(err)
- }
- os.Exit(0)
- }
|