UDP packets with python - python

I have a mobile router that can be configured by using different Python script. What I need to do is read all the packets arriving to the router in a concrete UDP port to copy this information in a .txt file afterwards.
Anyone can give me some tips about how can I do this using Python? How can I detect every time a packet arrives in to the router?
Thank you.

Here's a quick example of how to bind to a UDP port and do some action whenever a datagram is received:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('', 9800))
try:
while True:
result, who = s.recvfrom(256)
print result, who
finally:
s.close()

Related

Python - how to listen for UDP data on public ip and port?

I have a UDP socket to receive some data.
import socket
import struct
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('', 8321))
print("Listening")
while True:
message, address = server_socket.recvfrom(1024)
However, I would like to receive data externally, outside my local network.
Is there a way to do this?
I imagine this would be possible without port forwarding. Am I correct?
Isn't there something related to MAC addresses involved? Edit: nevermind, this is only for NAT.
It doesn't matter if a random public port is chosen each time I start the app, as long as I can communicate with it.

binding a UDP port and listening for connections

When I try to ping a Minecraft server via LAN, the documents say the following:
In Singeplayer there is a function called "Open to LAN". Minecraft (in the serverlist) binds a UDP port and listens for connections to 224.0.2.60:4445 (Yes, that is the actual IP, no matter in what network you are or what your local IP Address is)" ....... client side, bind a UDP socket and listen for connections. You can use a MulticastSocket for that.
I tried to implement this in Python in the following way:
import socket
UDP_IP = "224.0.2.60"
UDP_PORT = 4445
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))
while True:
data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
print("received message: %s" % data)
Which gave me an OSError: [WinError 10049] error.
Please help :( I have no idea what's wrong with my code.
By the way, sending packets to that port works, and the fake server shows up on the Minecraft app.
You cannot bind to a multicast address like that. It is somewhat more involved.
I recommend to read this article that explains all the details of using multicast with Python.

Retreiving multicast with python

I am working on a test tool for an existing piece of SW that outputs messages on multicast ip of 240.240.240.1 port 2349. The IP interface on which I am receiving the multicast messages is 192.168.0.4. I can observe these messages being pushed out onto the network via wireshark. Even netstat -ng shows the subscriptions. However, the receiver I wrote in python is not picking them up. I did borrow the code below from another thread, with the attempt to modify it to work in my situation.
import socket
import struct
import sys
multicast_group = '240.240.240.1'
server_address = (multicast_group, 2345)
# Create the socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Bind to the server address
sock.bind(server_address)
# Tell the operating system to add the socket to
# the multicast group on all interfaces.
group = socket.inet_aton(multicast_group)
src = bytearray(socket.inet_aton("192.168.0.4"))
mreq = bytearray(group)
mreq.extend(src)
sock.setsockopt(
socket.IPPROTO_IP,
socket.IP_ADD_MEMBERSHIP,
mreq)
# Receive/respond loop
while True:
print('\nwaiting to receive message')
data, address = sock.recvfrom(1024)
print('received {} bytes from {}'.format(
len(data), address))
print(data)
print('sending acknowledgement to', address)
sock.sendto(b'ack', address)
Any help would be appreciated in figuring out what I am doing wrong.
So I figured out my own problem. I had checked iptables as being an issue early on, with no luck. But I fixed/modified several things along the way to address the issues being seen. Turns out the code above works just fine, it was firewalld/iptables rules blocking the receipt of multicast.

How to read arduino data output using python via internet?

I have arduino project using uno and ethernet shield. I wan't to print arduino data output in python. I have done try this case using pySerial python and successful.
Then now, I wan't to try my python can read arduino data output over internet, not serial python.
Topology:
Arduino with eth. shield--->switch<---laptop
*Note: the switch have internet connection from my router.
Can you help me, guys?
The IP that you use here should be "localhost" since only the arduino needs the address of the computer and not the other way around. Your Python script is just listening for anyone to connect. Try this:
import socket
UDP_IP = "localhost" # this computer
UDP_PORT = 3939 # the port that the arduino should connect to
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))
while True:
data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
print "received message:", data

How to trigger Raspberry Pi 3 to take action from Server

I am currently developing a system where I need to send notification to Raspberry to run a Python file. It is much like a observer pattern design where my server is publisher and Raspberry is the observer. Worth to note that, I actually need to interact with one Raspberry at the time (even I have dozens of them). Specifically, on a specific event, I need to warn a single Raspberry that it has to take an action.
I searched for it literally for all the night but I could not find anything coming handy. Nothing really give me a clue how to implement this.
The most close answer I could find is this technology firm's product called PubNub which can actually work. However, as I need is a one-to-one interaction, this might be unnecessary because it is designed to publish a data to multiple clients.
Long story short, I need to trigger Raspberry to take some action in accordance to the some data coming from the server, whenever it receives the data.
Server is running on Amazon and implemented with Python 2.7.
Please do not hesitate to ask me for further detail, if I am missing any.
Thanks for all the supports,
EDIT
Just a recent update with an improvement to my answer. As far as I understand, sockets are able to manage this process. Such as from client (Raspberry in my case) listening for the server and server sending some data. Taken from this site, I managed to make a sample run on my computer, from my local. I used Port 5000 as their 'meeting point'.
Below is the code:
client.py
#!/usr/bin/env python
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 5000
BUFFER_SIZE = 1024
MESSAGE = b"Hello, World!"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()
print("received data:", data)
server.py
#!/usr/bin/env python
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 5000
BUFFER_SIZE = 20 # Normally 1024, but we want fast response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
print('Connection address:', addr)
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
print("received data:", data)
conn.send(data) # echo
conn.close()
However, I still have some questions.
Firstly, I want to learn whether the same thing work when I deploy the project and how. If that will work - lets say I have an url for the server like 'www.thisisanexampleurl.com' - simply assignign a port for it, will work?
Secondly, assuming first question is done, what is the way of making it continous so that it does not stop after receiving and sending data once. Because currently, when it makes the data transfer, it stops working.
Thanks again for the all support and again please do not hesitate to ask me for the further details i am missing any.
You should be able to do something this simple:
Run something like this on your pi:
import socket
s = socket.socket()
host = ""
port = 12345
s.bind((host, port))
s.listen(5)
while True:
try:
clientsock, addr = s.accept()
except OSError:
continue
message = clientsock.recv(20)
#the code you want to run
print("doing %s" % message)
clientsock.close()
And this on your server every time you want the pi to take action:
import socket
s = socket.socket()
host = "0.0.0.0"
port = 12345
s.connect((host, port))
s.send("foo")
s.close()
Have a look at Pyro4. It lets you avoid having to write network code at all and just write code that calls remote Python objects as if they were running on the same machine. In your case, the server could call a normal Python method on your Raspberry Pi to do something. It has many features but you can start with something extremely simple.
raspberry pi code:
import Pyro4
#Pyro4.expose
class Raspberry:
def something(self, arg):
print("called with:", arg)
return "hi from pi"
Pyro4.Daemon.serveSimple({Raspberry: "raspberry"})
server code to make the pi do something:
import Pyro4
rasp = Pyro4.Proxy("PYRONAME:raspberry")
print(rasp.something(42))

Categories