this is question is really focused on my problem and not relative to any of the other question I could find on this topic.
PSA: When I say "packet" I mean a full string received in a single socket.recv(maxsize)
I developed similar code for the same result on Java (my pref language) and it is ok, now I have to do in python.
I have two processes that run in parallel: 1-Normal client socket connected to a specific IP 2-A "client" Datagram socket binded to "ALL" IPs.
The normal socket is working correctly as I expect, while the datagram not.
I continuosly receive packets from a server (not mine and not opensource) at a rate of more than 5 per second, but I want to process only one of them every 3 seconds. In java I did just a "sleep" and it was ok, I was getting only the last live packet, while in Python with a "time.sleep(3)" the packets are queued (I don't know how and where) and not dropped.
I HAVE to drop them because those are not need and I have to do an HTTP call between one and the other so I can't fire an HTTP post for every set of data received at that rate!
here it is my "code" for the listening socket, some comments are for private code:
def listenPositions():
lsSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
lsSocket.bind(("0.0.0.0", 8787))
lsSocket.setblocking(0)
try:
while True:
ready = select.select([lsSocket], [], [], 1)
if ready[0]:
lsSocket.settimeout(1)
recvData = lsSocket.recv(16384)
if len(recvData) != 0:
recv = recvData[0:len(recvData)].decode("utf-8")
#print("LS: Received: " + recv)
strings = filter(None, str(recv).split('\n'))
print("Strings count=" + str(len(strings))+ ": " + str(strings))
for item in strings:
#parse the received strings as json and get the items
jsonPosition = json.loads(item)
strId = jsonPosition["id"]
coordinates = jsonPosition.get("coordinates")
if coordinates is None:
continue
print("coordinates not null:" + str(coordinates))
#DO THE HTTP POST REQUEST
time.sleep(3) #Pause the system for X seconds, but other packets are queued!
else:
print("LS: Received empty")
else:
print("LS: No data, timeout")
except Exception as e:
print(e)
#handle exceptions...
print("Exception, close everything")
When you have an open socket, all correctly addressed packets should be delivered to the application. We want to have our network connections as realiable as possible, don't we? Dropping a packet is an action of last resort.
If you want to get a packet only from time to time, you could create a listening socket, get a packet and close the socket.
However there is nothing easier than ignoring a packet. Just skip its processing and move on. The code below is incomplete, but hopefully expresses what I mean.
TIMEOUT = 1.0
INT = 3.0 # interval in seconds
# create udp_socket
last = time.time() - INT
udp_socket.settimeout(TIMEOUT)
while True:
try:
packet = udp_socket.recv(MAXSIZE)
except socket.timeout:
# handle recv timeout
continue # or break, or return
except OSError:
# handle recv error (Python 3.3+)
break # or continue, or return
now = time.time()
if now - last >= INT:
# process the packet
last = now
Please note that the select
is not needed if you read only from one source.