I sent a UDP broadcast using Python 3.7.3.
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.bind(('', 12345))
sock.settimeout(1)
sock.sendto('ABCD'.encode(), ('255.255.255.255', 5048))
while 1:
try:
data, addr = sock.recvfrom(1024)
except socket.timeout:
print('socket timeout')
sock.sendto('ABCD'.encode(), ('255.255.255.255', 5048))
I could not confirm the broadcast on Wire Shark.
[solved]
I changed the 'Npcap Loopback Adapter' to 'Disabled' in the Ethernet adapter option, and I was able to see the UDP packets from the wire shark.
But I do not know why this is happening.
I would like advice.
Related
I have a p2p simple chat app in python. A server code receives the IP and port of peers and sends each peer address to another:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('', 44444))
while True:
clients = []
while True:
data, address = sock.recvfrom(128)
clients.append(address)
sock.sendto(b'ready', address)
if len(clients) == 2:
break
c1 = clients.pop()
c2 = clients.pop()
try:
sock.sendto('{} {} {}'.format(c1[0], c1[1], c2[1]).encode(), c2)
sock.sendto('{} {} {}'.format(c2[0], c2[1], c1[1]).encode(), c1)
except Exception as e:
print(str(e))
In my client code, first I start sending client info to the server (This part works properly):
import socket
import threading
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
sock.bind(('', 40270))
sock.sendto(b'0', ('X.X.X.X', 44444))
while True:
data = sock.recv(1024).decode()
if data.strip() == 'ready':
break
ip, myport, dport = sock.recv(1024).decode().split(' ')
myport = int(myport)
dport = int(dport)
print('\n ip: {} , myport: {} , dest: {}'.format(ip, myport, sport))
This part of the code starts listening to the server after sending the current client's info to the server and when the other client gets connected, it receives its IP and port.
After connecting two clients and exchanging their addresses, a p2p connection is established between them.
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
sock.bind(('', myport))
sock.sendto(b'0', (ip, dport))
print('ready to exchange messages\n')
Then, I run a thread to start listening to the other client like this:
def listen():
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', myport))
while True:
data = s.recv(1024)
print('\rpeer: {}\n> '.format(data.decode()), end='')
listener = threading.Thread(target=listen, daemon=True)
listener.start()
Also, another socket is responsible to send messages:
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', myport))
while True:
msg = input('> ')
s.sendto(msg.encode(), (ip, dport))
After all, as I said before, the server exchange the IP and port of clients properly. But messages were not received by another client after sending.
I think the problem is about the wrong port choice while I do the exchange.
Regards.
It is completely functional on Linux. The problem just occurred on a windows machine.
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?
I am trying to learn to code sockets (in Python 3), I am simply trying to send a broadcast from a server and receive it from a client.
My problem is that whenever I try to send the packets to 255.255.255.255, it seems nothing is actually sent.
I tried to find the packets with wireshark but except on the loopback interface, I can't find any.
I can successfully send a message between the two computers when manually inputting the IP, and I also see the packets in wireshark.
Here's the code for the client
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.bind(("0.0.0.0", 5005))
while True:
# sock.sendto(bytes("hello", "utf-8"), ip_co)
data, addr = sock.recvfrom(1024)
print(data)
And here's the code for the server
import socket
from time import sleep
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) # UDP
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
# sock.settimeout(2)
while True:
sock.sendto(bytes("test", "utf-8"), ("255.255.255.255", 5005))
sleep(1)
main()
Sorry if the code is ugly, I am very new to sockets and to python.
The reason is that you are broadcasting on one interface and listening on another. See this answer UDP-Broadcast on all interfaces.
You need to broadcast on all interfaces, for example using the following (purely for demonstration) code. However, keep in mind that broadcasting over IP is a legacy feature which has been dropped from IPv6. Use multicasting instead.
import socket
from time import sleep
def main():
interfaces = socket.getaddrinfo(host=socket.gethostname(), port=None, family=socket.AF_INET)
allips = [ip[-1][0] for ip in interfaces]
msg = b'hello world'
while True:
for ip in allips:
print(f'sending on {ip}')
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) # UDP
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.bind((ip,0))
sock.sendto(msg, ("255.255.255.255", 5005))
sock.close()
sleep(2)
main()
If you are here to just know how to send broadcast and the solution of Mario don't work for you, because you are getting list of ips as 127.0.1.1, so there is a simpler solution:
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) as sock:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.sendto(msg, ("255.255.255.255", 5005))
Notice that the disadvantage here is that it will not go throw all the network interfaces, like Mario solution, just the one per the OS IP table. So keep in mind...
I'm searching for the best way to connect my app to multiple servers. For example, I need to send one message to IP 192.168.1.3 and then another message to IP 192.168.1.4.
I'm using mySocket.sendto(data, (IP,port)) but it is slow for me.
Exists another way to do this more efficiently?
Pseudo-code:
mySocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
mySocket.settimeout(1)
self.mySocket.bind((MY_IP, PORT))
Then I use a function to send:
mySocket.sendto(data_to_send, (IP_1, PORT))
data_rcv1, addr = mySocket.recvfrom(1024)
sleep(0.1)
mySocket.sendto(data_to_send, (IP_2, PORT))
data_rcv2, addr = mySocket.recvfrom(1024)
Thanks!
I have tried this:
s = socket.socket(socket.AF_INET, socket.SOCK_RAW,socket.IPPROTO_IP)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
s.bind(('', 69))
while True
try :
databuffer, (raddress, rport) = s.recvfrom(1024)
except socket.timeout:
logging.error("Write timeout on socket")
continue
But the result says nothing was received(no package!) in databuffer. But I used Wireshark that really captured the packets!
I have found some solutions: How Do I Use Raw Socket in Python?
The last example shows how to write a very simple network sniffer with raw sockets on Windows. The example requires administrator privileges to modify the interface:
import socket
# the public network interface
HOST = socket.gethostbyname(socket.gethostname())
# create a raw socket and bind it to the public interface
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
s.bind((HOST, 0))
# Include IP headers
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
# receive all packages
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
# receive a package
print s.recvfrom(65565)
# disabled promiscuous mode
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF) "
Mine:
HOST = socket.gethostbyname(socket.gethostname())
s = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_UDP)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
s.bind((HOST, 69))
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
It works! But there is another problem: the local port 69!
s.bind((HOST, 69))
Packets captured are all from port 0 but not 69!
I was wondering if there are even better ways to do that.
On os:windows server 2003 R2 standard edition sp2 -32bits
python 2.7.1