python – 如何在ZMQ套接字中启动/退出时清除缓冲区? (防止服务器与死客户端连接)

我在python中使用REQ / REP类型套接字进行ZMQ通信.有多个客户端尝试连接到一个服务器.客户端脚本中添加了超时以防止无限期等待.

问题是当服务器没有运行,并且客户端试图建立连接时,它的消息会被添加到队列缓冲区中,理想情况下,此时该队列缓冲区甚至不应该存在.当脚本开始运行并且新客户端连接时,服务器首先获取先前客户端的数据.这不应该发生.

当服务器启动时,它假定客户端已连接到它,因为它曾尝试连接,并且无法干净地退出(因为服务器已关闭).

在下面的代码中,当客户端第一次尝试时,它会获得ERR 03:服务器关闭,这是正确的,然后是错误断开连接.当服务器启动时,我得到连接的第一个客户端的ERR 02:Server Busy.这不应该发生.客户端应该能够在服务器启动并运行时与服务器无缝连接.

服务器代码:

import zmq

def server_fn():

context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://192.168.1.14:5555")
one=1
while one == 1:
    message = socket.recv()
    #start process if valid new connection
    if message == 'hello':
        socket.send(message) #ACK
        #keep session alive until application ends it.
        while one == 1:
            message = socket.recv()
            print("Received request: ", message)
            #exit connection
            if message == 'bye':
                socket.send(message)
                break
            #don't allow any client to connect if already busy
            if message == 'hello':
                socket.send ('ERR 00')
                continue
            #do all data communication here
    else:
        socket.send('ERR 01: Connection Error')
return

server_fn() 

客户代码:

import zmq 

class client:
    def clientInit(self):
        hello='hello'
        #zmq connection
        self.context = zmq.Context()
        print("Connecting to hello world server...")
        self.socket = self.context.socket(zmq.REQ)
        self.socket.connect("tcp://192.168.1.14:5555")
        #RCVTIMEO to prevent forever block 
        self.socket.setsockopt(zmq.RCVTIMEO, 5000)   
        #SNDTIME0 is needed since script may not up up yet
        self.socket.setsockopt(zmq.SNDTIMEO, 5000)   
        try:
            self.socket.send(hello)
        except:
            print "Sending hello failed."
        try:        
            echo = self.socket.recv() 
            if hello == echo:
                #connection established.
                commStatus = 'SUCCESS'
            elif echo == 'ERR 00':
                #connection busy
                commStatus = "ERR 00. Server busy."            
            else:
                #connection failed
                commStatus="ERR 02"            
        except:
            commStatus = "ERR 03. Server down."
        return commStatus   

    def clientQuit(self):
            try:
                self.socket.send('bye')
                self.socket.recv()              
            except:
                print "Error disconnecting."    

cObj = client()            
commStatus=cObj.clientInit()
print commStatus
cObj.clientQuit()

PS – 我觉得解决方案可能在于正确使用socket.bind和socket.connect.

解决方法:

回答我自己的问题 –

问题是第一个客户端在开始运行时发送服务器接受的消息,而不管客户端的状态如何.

为了防止这种情况,必须做两件事.最重要的是使用socket.close()来关闭客户端连接.其次,LINGER参数可以设置为低值或零.这将在套接字关闭后的超时值之后清除缓冲区.

class client:
    def clientInit(self):
...
            self.socket.setsockopt(zmq.LINGER, 100)   
...

def clientQuit(self):
        try:
            self.socket.send('bye')
            self.socket.recv() 
        except:
            print "Error disconnecting."    
        self.socket.close() 
上一篇:javascript-如何在nodejs中为zeromq设置套接字选项


下一篇:python – 试图了解zeromq高水印行为