Python- Retrieving data from a UDP server - python

I've been trying to attempt this for a while now, but I haven't made progress.
I have betterjoy (not my program, reference here: github.com/Davidobot/BetterJoy ) which creates a local UDP server at 127.0.0.1:26760, and through wireshark and some other programs (such as padtest/dsu controller test), I am able to verify packets with motion data being are sent from the server.
What I am trying to do is write a program which can receive the data being sent from the server, however so far, I have not been able to receive packets with my own code. This is my first time working with UDP, so I've spent a lot of time going through tutorials on creating clients, but unfortunately I have not been able to get any packets.
This is the code I am working with right now:
import socket
UDP_IP = "127.0.0.1"
UDP_PORT = 26760
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
msg = "this is a message"
sock.sendto(msg.encode("utf-8"), (UDP_IP, UDP_PORT))
print("message sent")
data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
print("received message: %s" % data)
Most of it is taken directly from the UDP communication documentation for python. I have tried a few different client code snippets other than this, but they are all generally following this same structure, and none have worked in retrieving the packets. It might be worth noting that wireshark lists the packets sent from the server as "loopback traffic", though I don't know how important that is.
Thanks in advance.

Related

Python UDP receiver raises timeout error with high package rate while wireshark receives data

I'm trying to make a simple UDP receiver, using python, to read a continuous data stream from a data aquisition device. This device can be configured to send data using UDP protocol to a certain IP and port. I configured it to send two data streams on port 4000 and 4001 both to ip: 192.168.0.10 (see wireshark screenshot below). The stream to port 4001 has a higher package rate. My laptop ip for the ethernet interface used is set statically at this ip in order to receive the data. I can receive the slow stream at port 4000 which works as expected. When I use the same code and set the port to 4001 I expected to read this data stream, instead I get a timeout exception.
I expected the biggest problem with high package rate udp would be loosing data because the buffer overflows which is not a big problem since loosing some packets is acceptable for my case. However if I get a timeout exception during the socket.recv(1024) call I thought that means there is no data in the buffer? Since wireshark does receive data I don't understand what is happening.
Here is a minimal example of what I am trying to do.
import socket
for i in range(3): # try multiple times
try:
socket_i = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
socket_i.settimeout(5)
socket_i.bind(('192.168.0.10', 4001)) #4000 works, 4001 does not
raw = socket_i.recv(1024)
socket_i.close()
print(raw)
except Exception as ex: # Exception is raised when using 4001: timed out
socket_i.close()
print('failed')
print(ex)
Wireshark printscreen; only 1 packet from port 4000 is shown, since this stream is slow.
I read similar questions:
Receive an high rate of UDP packets with python
Here it was concluded that python was the bottle neck. Also they received data, I don't receive anything, instead the socket.recv() times out. I don't think my package rate is that high, anyone thinks otherwise?
Receive an high rate of UDP packets with python
Here most of the data was received and only after some time the algorithm 'hangs on socket.recv()'. I tried increasing the buffer as suggested, using:
socket_i.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024*1024*1024)
Various values for buffer size are tried without luck. Setting large time out did not help.
Finally I tried using 'socketserver' package (the example udp server script):
import socketserver
class MyUDPHandler(socketserver.BaseRequestHandler):
"""
This class works similar to the TCP handler class, except that
self.request consists of a pair of data and client socket, and since
there is no connection the client address must be given explicitly
when sending data back via sendto().
"""
def handle(self):
data = self.request[0].strip()
socket = self.request[1]
print("{} wrote:".format(self.client_address[0]))
print(data)
# socket.sendto(data.upper(), self.client_address) #don't want to send stuff back
if __name__ == "__main__":
with socketserver.UDPServer(('192.168.0.10', 4001), MyUDPHandler) as server:
server.serve_forever()
Using port 4000 this gives the expected behaviour, for port 4001 the code hangs without doing anything (probably large timeout by default?). I guess 'socketserver' package runs ontop of'socket' package?
I hope someone can help!
Update:
I fixed my problem by making the udp receiver using pyshark. This is a bit hacky and I'm not satisfied with the method however for now it works. I figured if wireshark receives data pyshark might work as well. Any suggestions using 'socket' package are welcome!
code for hacky udp receiver
import pyshark
ip = '192.168.0.10'
port = 4001
capture = pyshark.LiveCapture(bpf_filter=f'dst host {ip} and dst port {port}', use_json=True, include_raw=True)
for pkt in capture.sniff_continuously():
raw = bytearray.fromhex(pkt.udp.payload_raw[0])
print(raw)

receiving messages through udp with delay python

I'm trying to understand how udp messages are received. I have an external tool that sends data over udp every 1 second, and a simple python script that receives them something like this.
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(ip,port)
while True:
data, addr = sock.recvfrom(num)
I can receive the data, but if I change the code to
while True:
data, addr = sock.recvfrom(num)
time.sleep(10)
I am still receiving the same messages as before, just at a slower rate. I was expecting the messages sent during the 'time.sleep(10)' will be lost (which I understand will be most if not all the messages). Is there an internal storage that stores all the messages sent, whether or not the receiver is receiving them?
A Socket has a buffer that has nothing to do with python but with the OS.
So yes, the udp packets are just sitting there and waiting for the application to read them from the buffer to the application memory.
Of course this buffer is limited so if you wait too long tthe buffer will get full you will start to lose packets.

Python socket listening to specific interface

I currently have a raspberry pi that is set up as a wifi to ethernet bridge. The raspberry pi acts as an access point to the entire ethernet subnet that I have. The subnet and the network bridge work perfectly but when I try to get my python program on the raspberry pi to listen to requests on the ethernet interface/subnet it doesn't seem to do that. It is set to bind the socket to ('',10000) but it never receives any messages. However, it is able to send messages via sockets to the subnet just fine, just not receive. I think it is listening to the wifi interface rather than the ethernet one but I'm not sure how to specify which interface the socket is suppose to listen to.
here is my receiving code
receive_group = ('',10000)
receive = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
receive.bind(receive_group)
while(True):
data, address = receive.recv(65536)
print(data)
The bind part should be correct. The receive part is wrong because recv only return the (bytes) data, you should use recvfrom to also get the sender address. But this should work:
import socket
receive = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
receive.bind(('', 10000))
while True:
data, address = receive.recvfrom(64)
print(data, address)
I used this code for the send part:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto(b'foo', (addr, 10000))
where addr is one of the (reachable) addresses of the receiver, and the receiver could successfully receive data from any of its interfaces.
To get something from socket.recv something must connect to this socket and send something. Are you sure that some program on the network is doing this?
For listening/sniffing to packets and network traffic, better use pyshark.
Turns out it wasn't anything with python. When I created the access point on the pi it created a firewall rule that blocked that port even though I never configured the firewall that way. Adding an exception to that port fixed my problem

Python : Receive UDP packets from port

I have a client which is creating packets and sending packets to a destination in a network which has been created using mininet. Now I am writing a python program at the destination to count the number of packets which has arrived. Now I know for sure that the packets are arriving at the destination (used tcpdump to verify it)
How do I go about it?
I thought of using this -
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
print s.recvfrom(5001)
But this seems to be slow. Is there any other alternative?
You want socket.IPPROTO_UDP for UDP packets, but otherwise, that's basically what you must do. No matter what other things you try, it's going to have to do those things.
Oh, and you'll want to do a socket.bind(('',PORT)) to bind it to the port you want it to listen on.

How can I get send() to block with UDP?

I am writing a simple UDP-based client/server app and testing with both the client/server on localhost, and I would like for the sender to know when send() would have blocked. I am using Python, so I think I can do:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setblocking(0)
s.connect(('127.0.0.1', 12345))
data = "x"
for i in range(0, 9000): # More than about 9000 gives an error
data += x
while True:
try:
s.send(data)
except socket.error as e:
print "Would have blocked"
# Do something useful here
I would like to test that my error-handling code works, so I would like to get send() to want to block. The problem is, I cannot figure out how to do that. I have tried have:
BUFFSIZE = 2000
input = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
input.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, BUFFSIZE)
input.bind(('127.0.0.1', 12345))
while True:
data = input.recv(BUFFSIZE)
time.sleep(100)
Between sleeping for 100 sec and setting a small receive buffer, I would have expected the buffer to have filled up. However, it never does. So how can I get the receive buffer to fill up so that send blocks?
I am using Mac OS Lion and the Macports version of Python 2.6.
UDP doesn't normally block. If the receiver has a full buffer, the packet gets silently discarded. This is by design. If you want reliable transport and blocking semantics, use TCP instead.
Comment: The reason TCP blocks is because the sender gets confirmation for every packet it sends. The sender only allows a certain amount of data "in transit" that does not have confirmation, and blocks when this threshold is reached. Since UDP does not send confirmation of received packets, the sender has no way of knowing when to block. Of course, it might decide to block if it saturates its Ethernet port, but with UDP there is no way to tell if your uplink is saturated, the receiver is hung, or gremlins ate your packet. No guarantees!

Categories

Resources