I have stable stream source with constant bitrate = 10.69Mbps.
I'm trying to create bitrate analyser using two approaches. First one is using scapy sniff function, another one is simple packet length counter using sock.recv()
.
The biggest problem is that in the first one, program is 'choking' every 3-5 seconds:(10.516,10.527,10.527,9.926,10.526[Mbps])
and in the second, results are much below true values:(10.251,10.201,10.201,10.221,10.201[Mbps])
What I concluded is that approach with scapy, has to capture about 40-50 datagrams more than another approach.
import socket
import struct
import timeit
from collections import Counter
from scapy.all import sniff
#___________________________part not affecting code_______________________
MCAST_GRP = '239.0.1.104'
MCAST_PORT = 12345
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)
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)
#__________________________Actual problems___________________________
packet_counts = Counter()
capturedPacketsSize = 0
## Defining custom function that sums sizes of captured packets
def custom_action(packet):
global capturedPacketsSize
capturedPacketsSize += len(packet)
#key = tuple(sorted([packet[0][1].src, packet[0][1].dst]))
#packet_counts.update([key])
#Scapy approach
print("_____.:| Starting analyse of bitrate! |:._____")
for x in range(10):
pkt = sniff(iface="eno4", filter="ip host 239.0.1.104", prn=custom_action, timeout=1)
MCbitrate = round((capturedPacketsSize*8)/(1024*1024),3)
print(MCbitrate)
capturedPacketsSize = 0
#General approach
totalSize = 0
print("_____.:| Starting analyse of bitrate! |:._____")
while 1:
stop = time.time() + 1
while (time.time()<stop):
#datagram = sock.recv(bufferUDP)
totalSize += len(sock.recv(bufferUDP))
theoreticalBitrate = (8*totalSize)/(1024*1024)
print(round(theoreticalBitrate,3))
totalSize = 0
So as you can see, idea of both is the same. But the results aren't.
Do you have any ideas how to increase accuracy without scapy approach
or remove 'choking' of scapy approach
?
__________________________________SOLUTION__________________________________
I believe that i concluded what may be wrong. After @Shir hint, i checked that in each solution (not considering scapy chokes) there are ~1016 +/- 2 packets per second.
The result of print(len(sock.recv()))
gives 1316 which is (I assume) size of decapsulated datagram. 1016*1316*8 = 10.696.448 bits.
By this simple math, I realised, that my denominator as Mega, should be (1000*1000) for Bits
, where it was (1024*1024) which is correct for Bytes
.