I'm trying to receive UDP Broadcast packets sent from FPGA connected via a LAN cable. the FPGA sends continuous packets to port 5001.
My python receiver code is simple:
from socket import *
s=socket(AF_INET, SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
s.bind(('', 5001))
print "trying to receive"
msg = s.recvfrom(1024)[0]
print msg
print "I'm outta here! Bye!"
I checked using Wireshark, and I found that the PC receives the packets. However, my Python code doesn't. I also checked sending packets from another local python code (to the same address and port) and my receiver got those packets.
Wireshark captures:
The issue was the firewall permissions for python
Related
I have a Python program that uses a sockets to send and receive UDP multicast messages on multicast IP address 224.0.1.1 and UDP port 20001.
On the receive the side, I create a single receive socket, and call socket.setsockopt once using socket option IP_ADD_MEMBERSHIP to join the IP multicast group.
However, Wireshark reports that the single call to setsockopt causes two separate join (IGMPv2 membership report) messages to be sent out:
One join message using Ethernet source address 01:00:52:00:01:01, which is the Ethernet multicast address corresponding to the IP multicast group.
One join message using Ethernet source address a8:66:7f:3a:2b:1a, which is the Ethernet unicast address corresponding to the physical "en0" interface over which the join message was sent.
On the send side, I create a single send socket, an call socket.connect to associate the socket with multicast IP address 224.0.1.1 and UDP port 20001.
I then call socket.send once to send a single test message. Because of the two separate join messages, the sent test message appears TWICE on the wire, once with destination Ethernet address 01:00:52:00:01:01 and once with destination Ethernet address a8:66:7f:3a:2b:1a.
On the receiving side, both messages are received separately. Thus each sent message is received TWICE.
The question is: how can I prevent this from happening?
A minimal example that reproduces the behavior is as follows:
import socket
import struct
import time
mcast_ipv4_address = "224.0.1.1"
port = 20001
group = (mcast_ipv4_address, port)
txsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
txsock.connect(group)
rxsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
req = struct.pack("=4sl", socket.inet_aton(mcast_ipv4_address), socket.INADDR_ANY)
rxsock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, req)
rxsock.bind(group)
time.sleep(1.0)
print("Sending single message...")
msg = b"test"
txsock.send(msg)
print("Sent {}".format(msg))
print("Receiving first message...")
msg = rxsock.recv(65535)
print("Received {}".format(msg))
print("Receiving second message...")
msg = rxsock.recv(65535)
print("Received {}".format(msg))
time.sleep(0.1)
Additional details:
1) The operating system is macOS High Sierra 10.13.5
2) The Python version is 3.5.1
3) The first sleep is essential; without it the problem does not occur because it takes some time for the join messages to be sent
4) The second sleep is not essential; it is there to make sure both test messages are seen by wireshark before the program terminates and the leave messages are sent.
5) I tried using the real IP address of the outgoing interface in stead of INADDR_ANY in the req structure, but it does not make any difference.
I found the answer to my own question:
If you disable the IP_MULTICAST_LOOP option on the sending socket, then:
1) Wireshark will STILL report two IGMPv2 join messages, same as before
2) Wireshark will STILL report two UDP multicast messages, same as before
3) However, the receiving socket will only receive a single UDP multicast message (the example program will block on "Receiving second message...")
Here is the updated code for macOS:
txsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
socket.IPPROTO_UDP)
txsock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 0) # <<< FIX
txsock.connect(group)
Annoyingly, the behavior on Linux is the opposite:
If you leave IP_MULTICAST_LOOP to its default value of enabled, as in the original example program, you will receive exactly one copy of the sent packet.
If you disable IP_MULTICAST_LOOP, as in the "fixed" example program, you will not receive any copy of the sent packet (at least not on AWS).
After further investigation, I found that the behavior does not depend on the platform on which the code runs (macOS vs Linux) but on the router to which the platform is connected.
I have a server where I have a script which sends UDP packets to my ip address and I have a client script on my PC that receives UDP packets.
#python3.6.1
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('myip', 49999))
data, address = sock.recvfrom(100)
print('Received {}'.format(data.decode('ascii')))
On the server side my scripts connects to ('myip', 49999) and starts sending packets.
I took my ip from ip4.me i tried to bind my socket to '0.0.0.0' too and i tried other ports nothing seems to work.
If that is the server script, i guess it should have a while loop in it:
while True:
data, address = sock.recvfrom(100)
print('Received {}'.format(data.decode('ascii')))
I was debugging a python program, the application can't receive udp packets as expected. Finally I found it was the UdpSocket.connect cause the UdpSocket to lose these packets. See below code:
def main:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.connect((server_ip, 9)) #This results in the issue
#Use sock.bind((local_ip, 12345))
#instead would solve the problem
localip, localport = sock.getsockname()
packet = GetRegisterData(localip, localport)
sock.sendto(packet, (server_ip, 5000)) #the host (server_ip, 5000) will
#always send back two udp packets
#to respond this statement
sleep(1)
while True:
response = sock.recv(1024) #packets from (server_ip, 5000) reached
#machine but this statement never return
if not len(response)
break
print response
I am very new to Python, and don't understand why this would happen. Any body helps explain this?
[Update]
I use tcpdump to capture packets, only to find the lost packets have reached the machine, but due to unkown reason the sock.recv just doesn't retuern. I want somebody to help explain why the sock.recv doesn't return everytime here.
You didn't mention where the packets that you expect to receive (but fail to) are coming from. I'm guessing they're not coming from the address you connected to, though. See the man page for connect(2) - which is what you're calling when you use this Python API - for information about why this matters. In particular:
If the socket sockfd is of type SOCK_DGRAM then addr is the address to which datagrams are sent by default, and the only address from which datagrams are received.
(emphasis mine).
I am having trouble receiving UDP packets on an Android device, so I want to find out if I am sending them properly. Using Wireshark, everytime I try to send a UDP packet to a remote address, the following error message occurs:
232646 311.898009000 172.56.16.78 192.168.0.3 UDP 64 Source port: 31947 Destination port: 5001 [ETHERNET FRAME CHECK SEQUENCE INCORRECT]
Frame check sequence: 0xf5b6d06d [incorrect, should be 0xb0c869e3]
Does anyone know how to fix this? Would this be the cause of why I could not receive UDP packets on my Android device?
Server Code:
import http.server
import socket
import threading
import socketserver
class ThreadedUDPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
data = self.request[0].strip().decode("utf-8")
print("{} Recieved: ".format(self.client_address) + data)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
response = data.upper()
sock.sendto(bytes(response, "utf-8"), self.client_address)
print("{} Sent: {}".format(self.client_address,response))
if __name__ == "__main__":
udpserver = ThreadedUDPServer((HOST,PORT+1), ThreadedUDPRequestHandler)
udp_thread = threading.Thread(target=udpserver.serve_forever)
udp_thread.daemon = True
udp_thread.start()
print("UDP serving at port", PORT+1)
while True:
pass
udpserver.shutdown()
It seems like you're sending packets using regular userspace sockets. In that case, there's very little chance that the packets are being sent malformed since the FCS is generated physically by the network interface card.
What you're probably seeing is an FCS error due to completely different reasons, which can be safely disregarded.
I'd look for other reasons for why the other device doesn't receive the packet, like firewalls or NAT. Start by using netcat or a similar tool for sending and receiving the UDP packets between the two machines.
I am trying to learn about network communications and sockets. Here is some code that I wrote:
Client code:
from socket import *
sock = socket(AF_INET, SOCK_DGRAM)
sock.bind('127.0.0.1', 3000)
data, addr = sock.recvfrom(1024)
print "Received data '" + data + "' from address:", addr
Server code:
from socket import *
sock = socket(AF_INET, SOCK_DGRAM)
sock.sendto("HELLO WORLD", ('127.0.0.1', 3000))
sock.close()
The client prints out: Received data 'HELLO WORLD!' from address: ('127.0.0.1', 60788)
To my understanding, the second member of the tuple is supposed to be the port. Furthermore, if I send several messages the number increase by 1 every time. Why is it not 3000?
As a side-note, are the htons and htonl functions necessary with the python API?
First of all: The scripts that you've written here would typically be regarded as a server and client, respectively, not client and server. This is because the server (the first script) is binding to a known port and waiting for a connection, while the client (the second script) is connecting to it from a random port and sending data.
To answer your questions directly:
Since you aren't binding the client to any specific port, it's choosing a new epheremal port for each socket, and those are being used sequentially. If the server were to send a packet back to that same host and port, it would be received by the client.
The htons and htonl functions are not generally necessary in Python. The socket module takes care of endian-swapping addresses and port numbers for you.
The port you are seeing is the port the data was sent from, not the port the data was sent to. When you don't specify the source port, and your "server" doesn't, the system assigns the socket a source port.