ZMQ推拉模式通信正常但tcpdump抓包源目地址相同、端口异常问题
问题根因
1. ZMQ的bind与connect逻辑写反
bind操作的作用是绑定本地的IP、端口监听外来连接,connect操作的作用是向远端的IP、端口主动发起连接。你代码里的逻辑完全颠倒了:
- 应用1的PUSH socket绑定了对端IP
1.1.1.2:5001,因为这个IP是你本地创建的tap口IP,所以bind可以成功,变成在本地监听该端口 - 应用1的PULL socket主动连接了本地IP
1.1.1.1:5000,刚好应用2的PUSH socket也绑定了这个本地端口,最终两个应用的连接都在本地内核回环路径里完成,根本没有走你预期的tap口跨IP传输。
2. 端口"不符"是对TCP机制的误解
你代码里配置的5000、5001是服务端监听的目的端口,TCP连接的发起方(connect端)的源端口是操作系统随机分配的临时端口,也就是你抓包里看到的45624、41982,这是TCP协议的正常机制,不是异常。
3. 源目IP相同是回环路径的正常表现
因为所有连接都在本地进程之间完成,内核通过回环路径转发数据包,不需要跨网卡传输,所以数据包的源IP和目的IP都是同一个本地IP。另外你抓包显示的IP是10.100.100.x而非你设置的1.1.1.x,说明你要么抓包选错了网卡,要么tap口的IP配置和你预期不一致,可以通过ip addr命令确认本地接口配置。
修复方法
把两个应用的bind和connect调用互换即可:
应用1修改后核心代码
string push_socat = "tcp://1.1.1.2:5001"; string pull_socat = "tcp://1.1.1.1:5000"; // PUSH发往对端,用connect zmq_send_socket.connect(push_socat.c_str()); // PULL收对端的消息,用bind绑定本地地址监听 zmq_recv_socket.bind(pull_socat.c_str());
应用2修改后核心代码
string push_socat = "tcp://1.1.1.1:5000"; string pull_socat = "tcp://1.1.1.2:5001"; zmq_send_socket.connect(push_socat.c_str()); zmq_recv_socket.bind(pull_socat.c_str());
修改后再抓对应tap口的数据包,就能看到源目IP分别为1.1.1.1、1.1.1.2的正常传输报文。
内容的提问来源于stack exchange,提问作者userr019283
相关产品推荐
相关产品推荐

