Я строю систему типа главный / подчиненный в golang. Когда подчиненное устройство (называемое гонщиком) подключено, оно отправляет пинг мастеру, сообщая, что оно подключено и готово принять данные, а затем начинает прослушивать порт. Порт, используемый для проверки связи и прослушивания, одинаков, но я проверяю, закрываю ли соединение после проверки связи. Мой вариант использования - использовать один и тот же порт для проверки связи и прослушивания, но я получаю ошибку bind: address already in use
, когда использую один и тот же порт для прослушивания. Иногда это работает, иногда нет. Что я делаю не так?
Полный код
main. go
package main
import (
"flag"
"log"
"strconv"
"time"
"github.com/goku321/line-racer/master"
"github.com/goku321/line-racer/model"
"github.com/goku321/line-racer/racer"
)
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
nodeType := flag.String("nodeType", "master", "type of node: master/racer")
masterIP := flag.String("masterIP", "127.0.0.1", "ip address of master process")
racers := flag.Int("racers", 2, "number of racers")
racerID := flag.Int("racerID", 0, "unique racer id (0 <= id < number of racers")
laps := flag.Int("laps", 10, "number of lap")
ip := flag.String("ip", "127.0.0.1", "ip address of the node")
port := flag.String("port", "3000", "port to use")
flag.Parse()
_, err := strconv.ParseInt(*port, 10, 64)
if err != nil {
log.Fatalf("error parsing port number: %s", *port)
}
if *nodeType == "master" {
m := master.New(*ip, *port, *racers, *laps)
m.GenerateLaps()
go m.Listen()
m.WaitForRacers()
m.StartRace()
m.PrintLaps()
} else {
r := racer.New(*racerID, *ip, *port, *masterIP)
r.SignalMaster(&model.Message{Source: r.IPAddr + ":" + r.Port})
time.Sleep(time.Second*60)
r.ListenForNewLap()
}
}
гонщик. go (подчиненный)
package racer
import (
"encoding/json"
"log"
"net"
"os"
"strconv"
"time"
"github.com/goku321/line-racer/model"
)
// Racer represents a racer
type Racer struct {
ID int
IPAddr string
Port string
Master string
Laps [][]model.Point
Status string
}
// SignalMaster sends a signal to master process
// with its coordinates
func (r *Racer) SignalMaster(m *model.Message) {
laddr, err := net.ResolveTCPAddr("tcp", r.IPAddr+":"+r.Port)
if err != nil {
log.Fatalf("error resolving tcp address: %s, reason: %v", r.IPAddr+":"+r.Port, err)
}
raddr, err := net.ResolveTCPAddr("tcp", r.Master+":3000")
if err != nil {
log.Fatalf("error resolving tcp address: %v", err)
}
for {
conn, err := net.DialTCP("tcp", laddr, raddr)
if err != nil {
log.Printf("connecting to master, %v", err)
time.Sleep(time.Second * 5)
} else {
m.Type = "ready"
m.Source = strconv.Itoa(r.ID)
m.Dest = r.Master + ":3000"
err := json.NewEncoder(conn).Encode(&m)
if err != nil {
log.Fatalf("error communicating to master: %v", err)
}
if err = conn.Close(); err != nil {
log.Fatal("unable to close connection")
}
break
}
}
}
// ListenForNewLap waits for master to get new coordinates
func (r *Racer) ListenForNewLap() {
ln, err := net.Listen("tcp", ":"+r.Port)
if err != nil {
log.Fatalf("racer %d: %v - %v", r.ID, err, time.Now())
}
log.Printf("racer %d: listening on %s:%s", r.ID, r.IPAddr, r.Port)
for {
conn, err := ln.Accept()
if err != nil {
log.Fatal(err)
}
go handleConnection(conn, r)
}
}
func handleConnection(conn net.Conn, r *Racer) {
log.Printf("racer %d: new lap from master", r.ID)
var msg model.Message
err := json.NewDecoder(conn).Decode(&msg)
if err != nil {
log.Printf("racer %d: %v", r.ID, err)
}
// close connection here as message has already been received
conn.Close()
if msg.Type == "race" {
r.Laps = append(r.Laps, msg.Coordinates)
r.race(msg.Coordinates)
} else if msg.Type == "kill" {
log.Printf("racer %d: kill signal received. racer will terminate", r.ID)
r.printLaps()
os.Exit(0)
}
}