I'm trying to implement simple DHCP client. The problem is receiving UDP broadcast packets on network interface that hasn't assigned ip address yet.
I think I can simplify my issue to following scripts that I execute in docker containers working in the same bridge network.
sender.py:
import socket
UDP_IP = "255.255.255.255"
UDP_PORT = 5005
MESSAGE = b"Hello, World!"
print("UDP target IP: %s" % UDP_IP)
print("UDP target port: %s" % UDP_PORT)
print("message: %s" % MESSAGE)
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.setsockopt(socket.SOL_SOCKET, 25, str(f"eth1" + '\0').encode('utf-8'))
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))
receiver.py:
import socket
UDP_IP = ""
UDP_PORT = 5005
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))
sock.setsockopt(socket.SOL_SOCKET, 25, str(f"eth1" + '\0').encode('utf-8'))
while True:
data, addr = sock.recvfrom(1024)
print("received message: %s" % data)
If i execute upper scripts when ip address is statically assigned to eth1- interface (172.1.2.2) i receive packet. But after deleting ip address:
ip addr del 172.1.2.2/24 dev eth1
I can't receive anything.
Of course i can observe sent packet on eth1 on receiver side by tcpdump.
How can i receive UDP broadcast packet, on interface that doesn't have assigned ip address ?
Related
I have an application that meeds to:
talks in UDP
support optionally disabling multicast.
treat multicast message the same way as unicast message but with few restrictions
I thought I should use same UDP socket to receive both unicast and multicast datagrams.
# udp_multicast_recv.py
# Python version used: 3.9.1
import socket
import struct
host = "224.1.1.1"
# host = "0.0.0.0"
listen_all = True
port = 5683
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
if listen_all:
s.bind(("", port))
else:
s.bind((host, port))
mreq = struct.pack("4sl", socket.inet_aton(host), socket.INADDR_ANY)
s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
data = None
print("Listening")
while True:
# data, addr = s.recvfrom(1024)
data, ancdata, msg_flags, addr = s.recvmsg(1024)
print(addr, ":", data, ancdata, msg_flags)
# udp_multicast_send.py
import socket
dest = "224.1.1.1"
dest = "192.168.86.188"
port = 5683
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.sendto("Hello world".encode(), (dest, port))
I soon noticed I need a way to distinguish multicast datagram from unicast datagram. But I was unable to find a solution nor related question on how to achieve this on the internet.
Hence the question: When receiving UDP datagram from same socket, is there a way to tell whether datagram is unicast or multicast?
In the image, the specs of the UDP package I aim to capture is shown through WireShark. The UDP packet comes from a different client attached to my router. However, when trying to capture this using socket through python, I keep on getting OSError: [Errno 99] Cannot assign requested address.
Currently I am doing following:
import sys
import socket
##Capture UDP packets
UDP_IP = "192.168.13.13"
UDP_PORT = 1667
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Bind the socket to the port
server_address = (UDP_IP, UDP_PORT)
print(sys.stderr, 'starting up on %s port %s' % server_address)
sock.bind(server_address)
while True:
print (sys.stderr, '\nwaiting to receive message')
data, address = sock.recvfrom(4096)
print (sys.stderr, 'received %s bytes from %s' % (len(data), address))
print (sys.stderr, data)
Is this the correct address to use?
I want to broadcast a message among four raspberry Pis . I programmed the code By socket programming in python with UDP protocol . In order to send the message I used the broadcast IP address (192.168.0.255) and I test that in terminal on my computer it is work , but when I execute the same code on the Pi it is not working and no message is sent . When I send a message between two Pis and use (IP + port) it is work and the message is sent .
Did any one know what I must to change in my code ?? or in my Pi?? How I can broadcast this message ??
I also use the instruction (('', UDP_PORT)) and not work on Pi.
#Client.py
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM )
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
UDP_IP = "192.168.0.255"
UDP_PORT = 50000
MSG = 'Hello, World!'
MESSAGE = str.encode(MSG)
print (("message:"), MSG )
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))
sock.close()
#server.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
UDP_IP = "192.168.0.101"
UDP_PORT = 5005
s.bind((UDP_IP, UDP_PORT))
print('socket is created')
while True:
data ,addr = s.recvfrom(1024)
print (('received message:') , data.decode("utf-8"))
So, I have this code here. This sender script give's me the output properly.
import socket
UDP_IP = "127.0.0.1"
UDP_PORT = 0
MESSAGE = "Hi, can you listen to this?"
print "UDP target IP:", UDP_IP
print "UDP target port:", UDP_PORT
print "message:", MESSAGE
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))
I tried to use this script on another host and try to establish a communication between the two. (Both the systems are on the same network ex. 00.000.00.xxx , only the xxx part varies)
import socket
UDP_IP = "127.0.0.1"
UDP_PORT = 0
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:", data
Here is the output
Traceback (most recent call last):
File "C:/Users/bshivaku/Desktop/SEnd_Udp_packets.py", line 9, in <module>
sock.bind((UDP_IP, UDP_PORT))
File "C:\Python27\Lib\socket.py", line 228, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 10049] The requested address is not valid in its context
I used the ip address of the receiver on the sender script and sender ip address on receiver
I am sure I made a mistake with the UDP_PORT so i used PORT= 0 and tried. How to request for port number? How do I establish the connection? If not the port, where am I going wrong?
When sending a message use a specific port, for example UDP_PORT=8765, otherwise if UDP_PORT is set to 0 then the system will chose a random port for you.
Use the ip address of the receiver host in the sender script and bind to any interface on the receiver script.
On the receiving side use the same UDP port number configured in the sender script.
receiver:
import socket
UDP_IP = "0.0.0.0"
UDP_PORT = 8543
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:", data
sender:
import socket
UDP_IP = "<ip_address_of_receiver>"
UDP_PORT = 8543
MESSAGE = "Hi, can you listen to this?"
print "UDP target IP:", UDP_IP
print "UDP target port:", UDP_PORT
print "message:", MESSAGE
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))
Aside the UDP addresses setting there are not any problems on python side.
About the error:
[Errno 10049] The requested address is not valid in its context
This normally stems from an attempt to bind to an address that is not valid for the local computer: so it seems that the loopback address 127.0.0.1 it is not configured on your machine.
Investigate on the sys admin side, for example check if the IPv4 network stack is enabled on your machine.
I am able to send and receive UDP messages in separate programs, but I'm not able to do the same task in one program.
import socket
UDP_IP = "192.168.1.178"
UDP_PORT = 8888
msg = 'test'
print "UDP target IP: ", UDP_IP
print "UDP target PORT: ", UDP_PORT
print "Message: ", msg
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(msg, (UDP_IP, UDP_PORT))
UDP_IP2 = "192.168.1.198"
sock.bind((UDP_IP2, UDP_PORT))
while True:
data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
print "received message:", data
With this program, I am able to send UDP messages, however, I am not able to receive any messages from the other machine.
What am I doing wrong?
Thanks in advance,
Mikkel
In your example you try to bind socket addr after sending, what's wrong.
Address can be bound to socket only before any data transfer.
If there is no explicit bind OS sets any free (unused) port number in range [1024, 65535] on first .send()/.recv() call.
Next, socket can be bound only to single IP (except special case '0.0.0.0' which means "all host's interfaces").