使用 ZMQ 时,从 Ubuntu 16.04 到 Windows 7 的出站 TCP 流量被阻止

Outbound TCP Traffic From Ubuntu 16.04 to Windows 7 is blocked when using ZMQ

我在服务器和客户端之间有一个用 Python 编写的 ZeroMQ PUB/SUB 连接。服务端发送消息,客户端打印出来

这些程序在同一台计算机上工作得很好(Ubuntu 16.04,或 Windows 7;两者都工作)。

当服务器在 Windows 7 机器上并且客户端在 Ubuntu 16.04 机器上时,它们也可以工作。

但是,如果服务器在 Ubuntu 16.04 机器上,那么 Windows 7 机器上的客户端无法连接到它。

此外,当我在两台单独的 Windows 7 台机器之间移动客户端和服务器程序时,通信没有问题。

有人知道问题出在哪里吗?

这里是客户端代码:

#Based on code found on this Stack Overflow post:
#

import cv2
import zmq
import base64
import numpy as np

context = zmq.Context()
footage_socket = context.socket(zmq.SUB)
address = 'tcp://192.168.128.229:5555'
footage_socket.connect(address)
footage_socket.setsockopt_string(zmq.SUBSCRIBE, unicode(''))

print "start"
print "connecting to ", address

while True:
    try:
        frame = footage_socket.recv_string()
        img = base64.b64decode(frame)
        npimg = np.fromstring(img, dtype=np.uint8)
        source = cv2.imdecode(npimg, 1)
        cv2.imshow("image", source)
        cv2.waitKey(1)

    except KeyboardInterrupt:
        cv2.destroyAllWindows()
        print "\n\nBye bye\n"
        break

这是服务器代码:

#Based on code found on this Stack Overflow post:
#

import cv2
import zmq
import base64

context = zmq.Context()
footage_socket = context.socket(zmq.PUB)
footage_socket.bind('tcp://*:5555')
footage_socket.setsockopt(zmq.CONFLATE, 1)

camera = cv2.VideoCapture(0)

while True:
    try:
        (grabbed, frame) = camera.read()
        frame = cv2.resize(frame, (640, 480))
        encoded, buffer = cv2.imencode('.png', frame)
        footage_socket.send_string(base64.b64encode(buffer))


    except KeyboardInterrupt:
        camera.release()
        cv2.destroyAllWindows()
        print "\n\nBye bye\n"
        break

最佳实践列表:

  • 解读:不靠重装成string-wrapped原创内容(已经发了很多string 在 post Python-3.0+ )
  • 中成为 byte 后的问题
  • 版本控制:并非所有版本的 ZeroMQ 核心设施都具有相同的作案手法(PUB/SUB 主题过滤发生在 PUB 在最近的版本中,而在 ZeroMQ 早期的 SUB 方面进行操作。版本很重要.
  • 性能: 尽可能避免核心数据流的开销 "external"。使用 base64.{b64encode()|b64decode()} 是这种不利的性能舒适度的一个例子,没有提供任何足够的好处。

  • 剖析、调整和检查任何基于 cv2 的帧处理的实际成本 ~ colour-space 转换可能需要 +170 [ms] p.i。 (在左下 window )

  • 可以以一种非常廉价的方式将任何进一步的细节添加到 aMessagePAYLOAD 中(通过 struct.pack( aPayloadMASK, .data, OptionA, OptionB, OptionC ) - 无论是旋转 aSeqNumUINT8, aUsecTimeSTAMP,还是任何其他人可能想添加的内容)

做-s PUB-side:

import numpy as np
import zmq
import cv2
import struct

print( "INF: this process uses {0: >10s} v.{1:}".format(  "ZMQ",  zmq.__version__ ) )
print( "INF: this process uses {0: >10s} v.{1:}".format(  "NUMPY", np.__version__ ) )
...
..
aPubSOCKET.setsockopt( zmq.LINGER,        0 )
aPubSOCKET.setsockopt( zmq.IMMEDIATE,     1 )
aPubSOCKET.setsockopt( zmq.TOS,           aTypeOfSERVICE_PREFERENCE_ID )
aPubSOCKET.setsockopt( zmq.SNDHWM,        4 )
aPubSOCKET.setsockopt( zmq.SNDBUF,        4*640*480*3 )
aPubSOCKET.setsockopt( zmq.CONFLATE,      1 )
...
..
.
aPayloadMAP = ">"+ ( 640 * 480 * 3 )*"B"
HiResCAM    = cv2.VideoCapture( 0 )

while True:
      try:
          ( _ , cv2HiResFRAME ) = HiResCAM.read()    # acquire FRAME
          aPubSOCKET.send( struct.pack( aPayloadMAP, # pack to aMsgPAYLOAD, once .resize()'d
                                        cv2.resize( cv2HiResFRAME,
                                                    ( 640, 480 )
                                                    ).data
                                        ),           # OpenCV 2.2+ natively uses numpy arrays W * H * D * unit8 in BGR-ordering ( BGRA, if alpha used )
                           zmq.NOBLOCK
                           )

      except KeyboardInterrupt:
            # ...

      finally:
            # gracefully terminate all OpenCV resources
            # gracefully terminate all ZeroMQ resources
            break

做-s SUB-边:

import numpy as np
import zmq
import cv2
import struct

print( "INF: this process uses {0: >10s} v.{1:}".format(  "ZMQ",  zmq.__version__ ) )
print( "INF: this process uses {0: >10s} v.{1:}".format(  "NUMPY", np.__version__ ) )
...
..
aSubSOCKET.setsockopt( zmq.LINGER,        0 )
aSubSOCKET.setsockopt( zmq.CONFLATE,      1 )
aSubSOCKET.setsockopt( zmq.MAXMSGSIZE,  100+640*480*3 )
aSubSOCKET.setsockopt( zmq.RCVHWM,        4 )
aSubSOCKET.setsockopt( zmq.RCVBUF,        4*640*480*3 )

aSubSOCKET.connect(                       address )
aSubSOCKET.setsockopt( zmq.SUBSCRIBE,    "" )

aPayloadMASK = ">" + ( 640 * 480 * 3 * "B" )

while True:
      try:
            cv2.imshow( "LAST IMAGERY AVAILABLE:",  struct.decode( aPayloadMASK, aSubSOCKET.recv() )
            cv2.waitKey( 1 )

      except KeyboardInterrupt:
            # ...

      finally:
            # gracefully terminate all OpenCV resources
            # gracefully terminate all ZeroMQ resources
            break