首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >获得绑定:已经在使用的地址,即使在关闭连接后,在高丽

获得绑定:已经在使用的地址,即使在关闭连接后,在高丽
EN

Stack Overflow用户
提问于 2020-04-05 21:19:25
回答 1查看 1.9K关注 0票数 1

我正在戈朗建造一个主从式系统。当从属程序(称为racer)启动时,它会发出主命令,告诉主它已经启动并准备好接收数据,然后开始监听端口。用于敲击和监听的端口是相同的,但我确保在敲击后关闭连接。我的用例是使用相同的端口进行点击和监听,但是当我使用相同的端口进行侦听时,我会得到bind: address already in use错误。有时起作用,有时不行。我做错什么了?

完整代码

main.go

代码语言:javascript
复制
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()
}

}

racer.go(slave)

代码语言:javascript
复制
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)
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-06 00:50:59

有些细节因实现而异,但一般来说,在关闭TCP连接之后,底层系统(主机OS )必须将其保持一段时间,以防重复数据包丢失。

此连接处于TIME_WAIT状态,可以阻止端口的进一步使用,因此不可能创建新的侦听器,除非向主机OS提供正确的底层设置。由于Go 1.5左右,Go自动在Linux上执行此操作:请参见第9929期。您使用的是什么主机操作系统?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61049648

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档