Simple Python UDP Server: trouble receiving packets from clients other than localhost - python

So, the very simple code that I'm trying to use is here: http://wiki.python.org/moin/UdpCommunication
(also here):
Sending:
import socket
UDP_IP = "127.0.0.1"
UDP_PORT = 5005
MESSAGE = "Hello, World!"
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))
Receiving:
import socket
UDP_IP = "127.0.0.1"
UDP_PORT = 5005
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
The code works fine when I run both applications on my computer. I put the sending code on my laptop with:
UDP_IP="IP address for my computer"
Everything else is the same. Yet, nothing happens. What am I doing incorrectly? I used wireshark and determined that the packet is being sent and received; however, the python program isn't receiving the packet. I'm very confused.
Any help is much appreciated.
Thanks in advance.

Try binding to all local interfaces on the receiving side:
sock.bind(("", UDP_PORT)) # could also use "0.0.0.0"
Note that the behavior of operating systems is not entirely logical (nor consistent) in terms of binding when receiving UDP packets, especially for multicast traffic. This is the behavior you get:
Linux: Binding to a specific IP will filter the incoming UDP packets and only the ones targeted at this specific IP will get through the filter. This means for example that multicast UDP packets received by an interface with IP 192.168.1.100 will not be received when binding to IP 192.168.1.100. On Linux the normal bind does not bind to an interface. Use setsockopt(SO_BINDTODEVICE) for this. Binding to 0.0.0.0 (or "" on Python) will always receive all UDP packets received by the machine on all interfaces, regardless of the destination IP, so this is usually the most useful option on Linux.
Windows: Binding to a specific IP will bind to the interface belonging to this IP, pretty much like setsockopt(SO_BINDTODEVICE) does on Linux. Incoming UDP packets are not filtered by this IP, so multicast traffic can be received even when binding to a concrete IP. (This is probably the first time the Windows behavior seems more consistent to me than the Linux behavior.)
Python does not abstract these OS specific differences away for sockets (as it does in other areas). As long as you have no explicit reason not to do so I suggest to always bind to 0.0.0.0.

eventually figured out my issue and it was pretty complex and highly localized,
I had a very similar problem happen to me. I realize that you have already solved this problem, however I thought it would be good to share how I solved the issue for me.
The issue I found was with my firewall settings. I found that the packets were being blocked by Windows Firewall.
I too had used Wireshark which showed that packets were being sent and received. It is important to note that Wireshark grabs packets at a much lower level than a Python application.
By running my code locally with a listener on one port and a client on another port on the same PC, the firewall wasn't blocking the packets. When I moved to interfacing with an external machine, the firewall rules came into play blocking the incoming packets.
Changing the firewall policy fixed this issue. There are numerous ways and inherent security risks to changing the firewall to make this work so I will leave that part up to the IT professionals. :-)

Make sure that the server port is open while trying to execute recvfrom call. If the destination port from which the socket reading was down then we get this error.
I got the same error and fixed by reading this link - http://www.linuxsa.org.au/mailing-list/2001-04/668.html

So if I want to send a message AND receive a response then how would the code look? Like this?
import socket
UDP_IP = "127.0.0.1"
UDP_PORT = 5005
MESSAGE = "Hello, World!"
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))
sock.bind((UDP_IP, UDP_PORT))
while True:
data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
print "received message:", data

Related

How send data between two devices using sockets in Python?

I'm using this code for the client:
import socket
HOST = "Server IP"
PORT = 5555
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
data = s.recv(1024)
print('Received', repr(data))
s.close()
And this code for the server:
import socket
HOST = "Client IP"
PORT = 5555
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
s.close()
and what I'd like to do is simply send some data from a device to another. The problem is that I could make it work just by sending data on devices on the same network (that is, send data from a CMD window to another, or send data from the PC to the phone, where I have Termux with Python installed, if the PC and the phone are connected to the same network).
However, how do I send data between two different networks? I suppose that in the HOST variable on the client side I should put the public IP address of the server and in the HOST variable on server side I should put the public IP address of the client right?
But then suppose that in the client network there are many devices connected, where do I specify the private IP address of the client to send the data to a specific device?
The short answer is that you can't -- most routers connected to the Internet these days include a firewall and/or NAT, both of which are explicitly designed to prevent Internet packets from the outside world from getting to devices on the local LAN, for security reasons. In particular, the private addresses assigned to devices on the LAN (192.168.1.5, 10.0.0.10, and so on) are non-routable, so they are not meaningful outside the context of the local network and cannot be used to route traffic across the Internet.
Obviously that's not the full answer, though, since various peer-to-peer programs in use today (e.g. Skype) do manage to communicate in the way you want to do; however, they all have to work around the above problem one way or another. Some ways they do it include:
Have the user of the LAN that is to receive the incoming TCP connection configure port forwarding on his router. This tells the router that any TCP connections received on a particular port should be automatically forwarded to the specified private IP address on the LAN. Downsides of this approach are that it opens a hole in the user's firewall that might be later exploited by bad actors, and that many users aren't willing (or even able) to reconfigure their routers in this way.
Run a server with an Internet-facing IP address, and have your program always connect to it. This server can then work as a proxy, forwarding TCP data from one connection to the other as necessary. This avoids the problem, at the cost of having to maintain your own 24/7 public-facing server and route all your traffic through it.
Use TCP hole punching to convince the router(s) to allow your incoming TCP connections by exploiting the rules/logic they (sometimes) use to decide when to allow incoming traffic. This gets you the direct connections you want, but it's fairly complicated to set up, doesn't work on all routers, and generally requires the implementation of step (2) (above) as a prerequisite, since the connection-bootstrapping process itself requires some communication that must be facilitated by a third-party.
to work, change s.listen() to s.listen(5)
I was able to connect from my network 192.168.1.x to other 192.168.2.x
Now, depending of your requirements you will need some configuration to work in the Internet.
the clients should have the IP depending the localization of your server, if server application is:
Connected direct to the Internet, client should have gateway IP address
Connected to a router, you can configure a DMZ (not recommended, not secure, just for tests) or configure ports (secure and recommended), the clients should have the gateway IP address of the router

Sockets: How would Peer to Peer chat work?

I am trying to make a P2P chat without manually adding users IP Address.
These scripts would send and receive UTF-8 message with UDP packets by manually specifying IP address.
# Send
# Let's say this code is executed from PC1.
import socket
PC2_IP = '192.160.4.169' # IP address is not valid, it is just for example.
UDP_PORT = 5005
MESSAGE = "Hey there!"
sock = socket.socket(socket.AF_INET,
socket.SOCK_DGRAM)
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))
Now as example let's execute Receiver script from PC2.
# Receive
# Let's say this code is executed from PC2.
import socket
ip = socket.gethostbyname(socket.gethostname())
udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp.bind((ip, 5005))
while True:
data, addr = udp.recvfrom(1024)
print data
This would work without any problems, The message would be received instantly after script executed.
But in theory how would i make a P2P chat without manually specifying IP addresses?
How would i make application get both users hostnames? Do i need to specify IP Addresses with socket.gethostbyname(socket.gethostname()) in both sender and reciever scripts?
If i need some extra necessary modules which one of them would it be? Can i use P2P module for sockets?
In the 1:1 case the first program doesn't need to know the address of anyone else. It just starts and waits. The second program needs to know the address of the first. As soon as it sends a "hello" the first program now knows the address of the second via recvfrom.
If you want no known addresses, well it stops being a Python question. Now you need to learn about autoconfiguration and network discovery protocols. Multicast? DNS Service Discovery? Bonjour?
That gets complicated real fast. There's a good reason why so many chat and chat-like Internet systems have a single server that everyone knows the address of.
Hope this helps.
maybe help this link P2P Berry Tella=BT
For this exist and python source(if need!)
Hope help you!

Listen to a port already in use for UDP packets in python?

Essentially I have a program, A, send results (just data points) in real time to another program, B, to handle. Each data point is sent as a UDP packet, on a specific port and 127.0.0.1, containing the point as a string. When B is not running, I can just do
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("127.0.0.1, port))
while True:
data, addr = sock.recvfrom(65565)
And then obviously when B is running, I get
[Errno 98] Address already in use
How can I see the packets sent on these ports? In the past (separate project) I had a packet sniffer using
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)
which saw all incoming and outgoing UDP packets, but that seems excessive. I only need to see the packets from a specific port. I'm fairly new to this lower level socket programming. Any help is appreciated
You can use scapy:
This is a small example:
from scapy.all import *
def callback(pkt):
pkt.show()
sniff(prn=callback, filter="tcp and ( port 25 or port 110)
No matter the packet sniffer you are using (whether it be wireshark or tcpdump), you can set packet filters to select a specific port. i.e. (tcpdump port port #) or (udp.port == port #).

Can't receive UDP packet in Python

I'm having trouble receiving a UDP packet sent from an FPGA in a python program. I've checked similar questions and did the following:
Checked that Wireshark can the see UDP packet
Disabled windows firewall in PC
Used sock.bind() since it's UDP packets
Manually set the destination MAC address on Ethernet frame since FPGA does not support ARP
Set dest IP to broadcast 10.10.255.255 for testing, no packets received
Set the UDP checksum of the packet from the sender to 0x0000
Here's the python receiver code:
import socket
import sys
UDP_IP = "10.10.10.87"
UDP_PORT = 4660
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))
print("Socket: "+str(sock.getsockname()))
while True:
data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
print(data)
print(addr)
sys.stdout.flush()
When tested against another python script that sends to 10.10.10.87:4660
(from another PC in the 10.10.10 network) the receiver script works fine. I've even tried to recreate the UDP pcket byte-by-byte in the FPGA from packets that I know are received OK (Differences are source IP, port & MAC, checksums (disabled), identification).
Here's the output for both packets from Wireshark:
Wireshark UDP packet (Python UDP packet that gets received OK on the left, Xilinx FPGA packet that is not received by python on the right)
I'm not sure what else to try. Any help would be appreciated.
Apparently the IPv4 header checksum from an FPGA calculation was wrong. It can get confusing to follow since the TTL (Time to Live) changes on a router hop, and the new TTL will also change the IPv4 header, forcing a new checksum per hop until it gets to Wireshark on the receiver end. By default Wireshark has IPv4 checksum validation disabled (as can be seen in the question screenshot), the answer is easier to spot with validation on.
I set the IPv4 checksum during packet construction to zero (x0000). It gets recalculated correctly at the router, and with the correct checksum Python can receive the packet.
I also tested a direct connection (without router) from the FPGA to the host PC. The IPv4 header also gets recalculated correctly (I'm not sure where, probably the PC's NIC?)
Hope this is useful to someone with similar problems.

Finding source IP-address when binding to 0.0.0.0

When binding a UDP socket to ("", 1234) or ("0.0.0.0", 1234), is it possible to find out what IP-address it will actually send from?
As you can see in the code below, getsockname only tells me what I bound to. But when I send a packet, I can see that the IP-address is, in my case, 10.0.0.2.
Do I have to infer this address myself by looking at my network interfaces? If so, that is fine, but is there a robust way of doing so?
from socket import *
s = socket(AF_INET, SOCK_DGRAM)
s.bind(("", 1234))
print(s.getsockname()) # prints ("0.0.0.0", 1234)
s.sendto("hello", ("10.0.0.3", 1234)) # sends from 10.0.0.2
I've tried doing
import socket
print(socket.gethostbyname(socket.gethostname()))
but that doesn't seem to be very reliable (in the case where I expected 10.0.0.2, I got 127.0.1.1).
I realize that by binding to 0.0.0.0, I bind to all local network interfaces. Does that mean that my source IP-address will be determined by the routing tables when I try to send something? If so, can I still get that address in a robust way from Python?
The IP address used when sending will be determined by the routing table as the packet is sent.
There might be platform specific ways of querying that routing table, but a fairly portable way is to
connect() the socket first.
You can use another socket just for querying this information too. e.g.
from socket import *
s = socket(AF_INET, SOCK_DGRAM)
s.bind(("", 1234))
print(s.getsockname()) # prints ("0.0.0.0", 1234)
sq = socket(AF_INET, SOCK_DGRAM)
sq.connect(("10.0.0.3", 1234))
print(sq.getsockname()[0])
sq.close()
s.sendto("hello", ("10.0.0.3", 1234)) # sends from 10.0.0.2
This is more a usually-you-do-not-need-it answer. It may not correspond to your usecase.
Have alook at socket.gethostbyname_ex(socket.gethostname()). It shows all possible IP-addresses and the host name. You can receive from all of those since you did not bind to any specific one of those. They will be your source ip addresses.
It is not necessairy for you to know the exact address you send from. The receiver may see another one if it goes behind a NAT, into the internet or through a VPN.
The receiver will then know where the packet came from and can send answers.
#Joachim_Pileborg is also right. It is not usually done.
If you need a specific interface, bind to it. If not, you probaply do not need it.

Categories