我在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中停止发送消息