在goroutine

时间:2019-07-01 18:42:54

标签: sockets go zeromq

我在Go中设置了一个套接字,用于向使用ZeroMQ进行通信的API收发数据。我们需要使用goroutines。我知道ZMQ套接字绝对不是线程安全的,并且为了确保它们正常运行,所有发送和接收都应在同一线程中完成。

我可以从所有API请求接收所有数据,但从一个特定的API调用获得的数据除外,这是我们需要响应的心跳,以使连接保持活动状态。

在此API中,可以做出多个请求,这些请求可以导致数据以及心跳请求被发送回。其他每个API请求都会发送回数据,等待大约5秒钟,然后发送使连接保持活动所需的心跳请求。使用单个线程运行代码时,我们可以从每个API调用中接收心跳信号。但是,当我通过goroutine运行相同的函数时,我会从每个API函数(除了其中一个)返回心跳请求。

设置套接字

import(
    "fmt"
    "os"
    zmq "github.com/pebbe/zmq4"
)

func testCode() {
    context, err := zmq.NewContext()

    if err != nil {
        fmt.Println("context err: ", err)
        return
    }

    //create Request Socket to talk to Request Server
    fmt.Fprint(os.Stdout,"Attempting to connect to Request Server...")
    sock, err := context.NewSocket(zmq.DEALER)
    if err != nil {
        fmt.Println("socket err: ", err)
        return
    }

    connection.RequestSocket = sock

    err = connection.RequestSocket.Connect(REQUEST_URL)
    if err != nil {
        fmt.Println("connect err: ", err)
        return
    }
}


//build the data to be sent up here

    ...

    _, err := socket.SendBytes(bufToSend, 0)
    if err != nil {
        fmt.Println("send err: ", err)
        return
    }

//receive all necessary data from the server
    for mask & info == 0 { 
        reply, err := socket.RecvBytes(0)
        if err != nil {
            fmt.Println("err: ", err)
            return
        }
        //process the data
        ...
}

因此,当我在另一个文件中运行此主要功能时,我们会从每个API请求中接收所有正确的数据和心跳请求

func main() {
    testCode()
    for {
    }
}

但是,当我将testCode()设为goroutine(如下所示)时,我仅收到一个API调用就无法收到心跳请求

func main() {
    go testCode()
    for {
    }
}

有趣的是,我监视了通过我们与之通信的端口进出的所有TCP,并确认该心跳请求是由API发送的。因此,正在发送心跳请求,Wireshark将数据识别为来自API的消息,但对于某个特定的API调用,我没有通过套接字接收到它。每个其他API调用都会发送心跳请求,我可以在程序中看到收到了它们。

我确保套接字的所有创建,发送和接收都在一个线程内完成。我对于为什么会发生此问题以及为什么仅对一个API调用而不是对所有API调用都发生感到困惑。

更新:显然对于未接收到心跳信号的API调用,我没有收到来自API的所有数据。在需要发送的36872条消息中,我收到了大约18910条消息。我不知道为什么一段时间后它只是在goroutine中停止发送消息

0 个答案:

没有答案