zmq.error.ZMQError: 非套接字上的套接字操作:如何在关闭之前找到活动的套接字?

3

在我的应用程序中,我创建了2个套接字,并为此使用try/except:

try:
    socketA.connect("tcp://localhost:5557")
    socketB.bind("tcp://localhost:5558")
except zmq.ZMQError as e:

    if e.errno == zmq.EINVAL:
        logger.error("Endpoint supplied is invalid")
    else:
        logger.error("The ZeroMQ error with an error number {0}".format(e.errno))
        raise ZMQError(e)
    cleanUp()

如果由于某种原因,其中一个套接字无法 .connect()/.bind(),我想在 cleanUp() 函数中关闭两个套接字并终止上下文,但在关闭它们之前,我如何知道哪些套接字是活动的?
ZeroMQ 在正常关闭套接字之前提供有关活动套接字的任何信息吗?
2个回答

4

鉴于上述逻辑,让我们采用另一种方法:

情况A:两个套接字分别都执行了.connect().bind()
情况B:其中任何一个套接字未能成功执行。

 try:
       socketA.connect(   "tcp://localhost:5557" )
       socketA.setsockopt( zmq.LINGER, 0 )
       try:
            socketB.bind(      "tcp://localhost:5558" )
            socketB.setsockopt( zmq.LINGER, 0 )

       except zmq.ZMQError as e:

            if ( e.errno in ( zmq.EINVAL, 
                              zmq.EPROTONOSUPPORT,
                              zmq.ENOCOMPATPROTO,
                              zmq.EADDRINUSE,
                              zmq.EADDRNOTAVAIL,
                              )
                 ):
                 logger.error( "ZeroMQ TransportClass / Endpoint cannot be setup for [socketB]." )

            if ( e.errno in ( zmq.ENODEV,
                              zmq.ENOTSOCK,
                              )
                 ):
                 logger.error( "ZeroMQ request was made against a non-existent device or not using a valid socket [socketB]." )

            if ( e.errno in ( zmq.ETERM,
                              zmq.EMTHREAD,
                              )
                 ):
                 logger.error( "ZeroMQ Context is not in a state to handle this request for [socketB]." )


            cleanUp( aContextINSTANCE, [ socketA, socketB, ] )

  except zmq.ZMQError as e:

            if ( e.errno in ( zmq.EINVAL,
                              zmq.EPROTONOSUPPORT,
                              zmq.ENOCOMPATPROTO,
                              )
                 ):
                 logger.error( "ZeroMQ TransportClass / Endpoint cannot be setup for [socketA]." )

            if ( e.errno in ( zmq.ETERM,
                              zmq.EMTHREAD,
                              )
                 ):
                 logger.error( "ZeroMQ Context is not ready to handle this request for [socketA]." )

            if ( e.errno in ( zmq.ENOTSOCK, ) ):
                 logger.error( "ZeroMQ operation was requested, but not on a valid [socketA]." )

       cleanUp( aContextINSTANCE, [ socketA, ] )

finally:
      # ...
      pass

def cleanUp( aContextToTERMINATE, aListOfSocketsToCLOSE = [] ):
    for      aSocket in aListOfSocketsToCLOSE:
        try:
             aSocket.close()             # external responsibility to setup LINGER as zero right at aSocket instantiation point
        except:
             pass
    try:
         aContextToTERMINATE.term()
    except:
         pass
    finally:
         # ...
         pass

1
谢谢你的回答!你为什么将linger设置为0?我在关闭套接字之前将其设置为-1,因为我希望即使在发送几条消息后关闭套接字,数据仍然可以在传输线上可用。 - NoName
当然有原因。任何非零的“LINGER”都会在尝试.close()时阻塞,分布式系统应该遵循公平原则,不应该阻塞。即使程序关闭,它也应该表现得无阻塞,以免失去控制——在阻塞状态下,您的代码对发生的事情没有任何控制,只是被动地停留在外部事件的沉默中(这些事件可能永远不会发生...)。阻塞资源和失去控制通常不是一个好主意,不是吗? - user3666197

1
我不完全确定你所说的“哪些套接字是活动的”的含义。无论哪个connect/bind调用失败,都必须关闭两个套接字。在C libzmq术语中,zmq_close不是zmq_connect/zmq_bind的对应项,而是zmq_socket的对应项。在pyzmq中,zmq_socket已经由Socket.__init__调用。请保留HTML标签,只需翻译。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接