上网。拨号覆盖现有连接

问题描述 投票:0回答:1

我正在编写一个应用程序来管理多个设备之间的连接,但是当启动新连接时,即使在新的 goroutine 中,网络连接接口似乎也会被覆盖。

主应用程序在切片中创建设备,并在启动时调用以下命令(通信通道存储在相同的结构中,以便将来参考):

for _, device := range devices {
        fmt.Printf("Starting device at %v\n", device.ipAddress)
        go device.run(device.outboundChannel, device.inboundChannel)
        success := <-device.outboundChannel
        if success.section == 0 && success.value == true {
            fmt.Printf("Device at %v started successfully!\n", device.ipAddress)
        }
    }

在内部,每个例程运行以下内容:

func (a *ani22) run(outComms chan<- aniCommand, inComms <-chan aniCommand) {
    initErr := a.init()
    if initErr != nil {
        outComms <- aniCommand{3, 0, false, false, initErr.Error()}
    }
    outComms <- aniCommand{0, 0, true, true, "Connected!"}
    fmt.Printf("Device at %v now monitoring!\n", a.ipAddress)
    for {
        // Application loop happens here
    }
}


func (a *ani22) init() error {
    if a.connection != nil {
        return errors.New(fmt.Sprintf("Cannot connect to %v as connection already esablished!\n", a.ipAddress))
    }
    if a.ipAddress == "" {
        return errors.New("No IP Address specified!")
    }
    timeout := 5 * time.Second
    fmt.Printf("Dialling IP %v\n", a.ipAddress)
    dialErr := errors.New("")
    a.connection, dialErr = net.DialTimeout("tcp", a.ipAddress, timeout)
    if dialErr != nil {
        return dialErr
    }
    return nil
}

当在切片中使用单个设备运行时,它可以正常工作,但是当添加任何其他设备时,它会在一次成功连接后阻塞,几乎就像下一个设备的连接被覆盖一样,尽管它位于单独的 goroutine 中。

go tcp ip goroutine
1个回答
0
投票

TLDR - 我没有正确检查所有我的比赛条件。

由于我实例化设备数组的方式,我似乎遇到了错误。

该数组是从导入的 CSV 文件生成的(为了清楚起见,省略了样板文件)。原始代码的工作原理如下:

type ani22 struct {
ipAddress       string
connection      net.Conn
chan1Led        bool
chan2Led        bool
inboundChannel  chan aniCommand
outboundChannel chan aniCommand
}

func import () ([]ani22, map[int]ani22Channel, error) {
var aniList []ani22 // Blank array to hold devices

deviceMap := make(map[int]ani22Channel)

for line := range lines {
    var tempAni ani22 // Make a temporary device, then fill in the details
    tempAni.ipAddress = lines[line][0] + ":2202"
    chan1Id, _ := strconv.Atoi(lines[line][1])
    tempChannel := deviceMap[chan1Id]
    if tempChannel.ipAddress != "" {
        continue
    } else {
        tempChannel.ipAddress = tempAni.ipAddress
        tempChannel.port = 1
        deviceMap[chan1Id] = tempChannel
    }
    chan2Id, _ := strconv.Atoi(lines[line][2])
    tempChannel = deviceMap[chan2Id]
    if tempChannel.ipAddress != "" {
        continue
    } else {
        tempChannel.ipAddress = tempAni.ipAddress
        tempChannel.port = 2
        deviceMap[chan2Id] = tempChannel
    }
    tempAni.outboundChannel = make(chan aniCommand)
    tempAni.inboundChannel = make(chan aniCommand)
    aniList = append(aniList, tempAni)
}
return aniList, deviceMap, nil
}

此代码不会激活类型中的 net.Conn 项,该项在 goroutine 脱离时调用的 a.init() 函数中处理:

func (a *ani22) init() error {
if a.connection != nil {
    return errors.New(fmt.Sprintf("Cannot connect to %v as connection already esablished!\n", a.ipAddress))
}
if a.ipAddress == "" {
    return errors.New("No IP Address specified!")
}
timeout := 5 * time.Second
fmt.Printf("Dialling IP %v\n", a.ipAddress)
dialErr := errors.New("")
a.connection, dialErr = net.DialTimeout("tcp", a.ipAddress, timeout)
if dialErr != nil {
    return dialErr
}
return nil
}

当项目附加到数组时,看起来好像 net.Conn 对象/接口被默认分配。似乎已经解决了这个问题的新方法:

func import () ([]ani22, map[int]ani22Channel, error) {
var aniList []ani22
deviceMap := make(map[int]ani22Channel)

for line := range lines {
    var tempAni ani22
    tempAni.ipAddress = lines[line][0] + ":2202"
    chan1Id, _ := strconv.Atoi(lines[line][1])
    tempChannel := deviceMap[chan1Id]
    if tempChannel.ipAddress != "" {
        continue
    } else {
        tempChannel.ipAddress = tempAni.ipAddress
        tempChannel.port = 1
        deviceMap[chan1Id] = tempChannel
    }
    chan2Id, _ := strconv.Atoi(lines[line][2])
    tempChannel = deviceMap[chan2Id]
    if tempChannel.ipAddress != "" {
        continue
    } else {
        tempChannel.ipAddress = tempAni.ipAddress
        tempChannel.port = 2
        deviceMap[chan2Id] = tempChannel
    }
    tempAni.outboundChannel = make(chan aniCommand)
    tempAni.inboundChannel = make(chan aniCommand)
// Additional code relocated from main function, starting connection and routine before returning the array
    fmt.Printf("Starting device at %v\n", tempAni.ipAddress)
    go tempAni.run(tempAni.outboundChannel, tempAni.inboundChannel)
    success := <-tempAni.outboundChannel
    if success.section == 0 && success.value == true {
        fmt.Printf("Device at %v started successfully!\n", tempAni.ipAddress)
    }
    aniList = append(aniList, tempAni)
}
return aniList, deviceMap, nil
}

我认为,通过在移动连接之前确保连接处于活动状态,我们可以确保它是唯一的,而不是让编译器决定处理“未使用”的变量。

© www.soinside.com 2019 - 2024. All rights reserved.