Python与Wireshark捕获UDP组播包数量差异的原因及解决方案问询
First, let's clarify your calculation question: yes, 769 * 1328 = 1021232 bytes (roughly 1MB) is mathematically correct. The big gap between this and your 10.5MB video file is because VLC is streaming the video, not sending the entire file all at once. It sends data at a rate matching the video's bitrate, so Wireshark is only capturing the packets transmitted during your capture window—not the full file. That's normal behavior for streaming.
Now, onto the main problem: why is Python receiving fewer packets than Wireshark? There are a few common culprits here, with straightforward fixes:
1. UDP Receive Buffer Overflow
By default, your OS's UDP receive buffer is relatively small. If packets arrive faster than your Python code can process them, the buffer fills up, and the OS drops excess packets (which Wireshark can still see because it captures traffic before the OS's buffer).
Fix this by increasing the buffer size with the SO_RCVBUF option:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 262144) # 256KB buffer, adjust as needed
You can go higher (like 524288 for 512KB) if you're dealing with high-throughput streams.
2. Slow Terminal Output Blocking Receives
Your original code prints every packet count immediately with print(counter). Terminal I/O is extremely slow compared to network operations—this creates a bottleneck that makes your code miss incoming packets while it waits to write to the console.
Fix this by reducing print frequency, e.g., print only every 100 packets (or use logging to a file instead):
if counter % 100 == 0: print(f"Received {counter} packets so far")
3. Fixed recv() Size Might Cause Truncation
You're using sock.recv(1328) assuming all packets are exactly that size. While VLC might send packets of that size, if any packet is larger (due to MTU variations or stream adjustments), recv() will truncate it, and you won't count the full packet (or might miss subsequent data).
Use a larger buffer to ensure you capture full packets:
datagram = sock.recv(4096) # 4KB buffer, more than enough for typical UDP multicast packets
4. Improved Code for Accurate Counting & Bitrate Calculation
Here's a revised version of your code that addresses the above issues and adds proper bitrate tracking (using total bytes instead of just packet count, since packet sizes can vary slightly):
import socket import struct import time MCAST_GRP = '239.200.200.1' MCAST_PORT = 5252 IS_ALL_GROUPS = True sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Increase receive buffer size to reduce overflow sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 262144) if IS_ALL_GROUPS: sock.bind(('', MCAST_PORT)) else: sock.bind((MCAST_GRP, MCAST_PORT)) mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) counter = 0 total_bytes = 0 start_time = time.time() print("Entering receive loop...") while True: datagram = sock.recv(4096) counter += 1 total_bytes += len(datagram) # Calculate and print bitrate every second elapsed_time = time.time() - start_time if elapsed_time >= 1.0: bitrate_kbps = (total_bytes * 8) / elapsed_time / 1000 # Convert bytes to kilobits per second print(f"Packets received: {counter} | Total bytes: {total_bytes} | Bitrate: {bitrate_kbps:.2f} kbps") # Reset counters for next interval counter = 0 total_bytes = 0 start_time = time.time()
Additional Checks
- Verify OS-level UDP packet loss: On Linux, run
netstat -s | grep UDPto check for "packet receive errors". On Windows, use Performance Monitor to look at UDP receive errors. - Ensure your network interface isn't dropping packets due to high load.
With these changes, your Python packet count should be much closer to what Wireshark captures, and your bitrate calculation will be more accurate since it uses actual received bytes rather than assumed packet sizes.
内容的提问来源于stack exchange,提问作者Yenjay

