Why python raises exception on udp recvfrom - python

I have realy simple python27 script on Windows10
It is just sends messages and waits for reply using udp socket
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))
sock.recvfrom(1200)
On Windows 10 it raises exception
Traceback (most recent call last):
File "simple.py", line 14, in <module>
print sock.recv(1200)
socket.error: [Errno 10054]
On Linux it works fine.
What i am doing wrong ?

The first several lines of your program are opening a socket to send data which all is fine. But the sock.recvfrom line doesn't have an associated bind with it.
In other words, when you send on UDP you shouldn't expect to receive anything back. If you want to send a message and then wait for a reply (which will not be automatic from a remote system) you need to bind the socket to a listening port.
This site: https://wiki.python.org/moin/UdpCommunication has some great references.

I found solution here Windows UDP sockets: recvfrom() fails with error 10054 Author made the same. He ignores this error. But maybe it is true way of solving this problem.
I just put recvfrom in while and wrapped it with try..except
And I ignore any errors. It worked for me

Related

"[Errno 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted" after closing and reopening Python socket

I have this code:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind(('10.0.0.253', 8080))
except:
s.close()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('10.0.0.253', 8080))
s.listen(1)
conn, addr = s.accept()
which binds, then if it encounters an error with that, destroys the socket then creates a new one and binds it to the same IP and port. For some reason, even after closing the socket, I get this error:
Traceback (most recent call last):
File "C:\Users\other\Desktop\tcpReverseShell_Server.py", line 68, in <module>
main()
File "C:\Users\other\Desktop\tcpReverseShell_Server.py", line 66, in main
connect()
File "C:\Users\other\Desktop\tcpReverseShell_Server.py", line 43, in connect
s.bind(('10.0.0.253', 8080))
File "C:\Python27\lib\socket.py", line 228, in meth
return getattr(self._sock,name)(*args)
error: [Errno 10048] Only one usage of each socket address (protocol/network
address/port) is normally permitted
The only solution I've found is to use s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1), but when I try that I get this error: [Errno 10013] An attempt was made to access a socket in a way forbidden by its access permissions. I
I am on Windows 10, Python 2.7.13.
I can simulate your problem by running the python script twice concurrently. The problem is that some other application is currently also using the socket.
In your code, the except block is triggered when your socket fails to bind. However, when you try to .close() the socket and try again, it does nothing as it is trying to .close() an unbound socket. Hence, your code is equivalent to:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('10.0.0.253', 8080))
s.listen(1)
conn, addr = s.accept()
Note that when you .close() the socket, it also does not .close() the currently bound application, it attempts to .close() to socket object you created. So, trying to bind the socket again will fail.
To find out what is using the socket, you can use netstat:
netstat -aon | findstr :8080
This should give you something like:
TCP 127.0.0.1:8080 0.0.0.0:0 LISTENING 6604
Then, if you want to kill it forcefully, you can use TaskKill and the application's PID:
TaskKill /PID 6604 /F

Cannot listen for UDP packets in Python- socket.error: [Errno 49] Can't assign requested address

I am trying to listen for UDP packets i am sending across my local network.
I have tried using https://wiki.python.org/moin/UdpCommunication with no joy and many other tutorials.
I am sending this packet off a windows laptop
import socket
import time
Host = '192.168.1.7'
Port = 5050
Message = 'hello world'+time.asctime()
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
sock.sendto(Message(Host,Port)
print 'sent', Message
time.sleep(5)
I have used the following to try and receive the UDP packets
import socket
Host = '192.168.1.138'
Port = 5050
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((Host, 5050))
while True:
recieved = sock.recv(1024)
print recieved
and
import socket
UDP_IP = "192.168.1.138"
UDP_PORT = 5050
sock = socket.socket(socket.AF_INET,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
I have ran the following recieve method on localhost and works perfectly fine but as soon as i assign an ip address of a device on my Local area network i get the following:
/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /Users/Myname/Desktop/untitled/recieve.py
Traceback (most recent call last):
File "/Users/Myname/Desktop/untitled/recieve.py", line 12, in <module>
sock.bind((UDP_IP, UDP_PORT))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 228, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 49] Can't assign requested address
Process finished with exit code 1
I tested this on 4 different devices all running python 2.7 and this is the same message i got. It was ran on a windows 7 laptop, MacBook, Kali Linux laptop, and PIXEL Raspbian on a raspberryPi
if you use socket.bind(("localhost", 80)) or socket.bind(("127.0.0.1", 80)) you will still have a “server” socket, but it will only be visible within the same machine.
You can try socket.bind(("", 80)) to tell the socket to be reachable by any address the machine may have.

Unable to send or troubleshoot UDP packet in Python 2.7

I am attempting to send packets to my "wifi lights" lighting system (like Philips Hue). I have documentation here that describes needing to send udp packets to my "bridge" using port 8899 which I have the IP address for.
All UDP Commands are 3 Bytes.
i.e. to turn all RGBW COLOR Wifi Lights Smart lights to ON then send
the TCP/IP UDP packet of:  0x42 0x00 0x55
The only way I could figure how to do in python was to chain them together as MESSAGE below. sendto() requires a string and won't accept hex or int.
import socket
UDP_IP1 = '192.168.0.104'
UDP_PORT = 8899
MESSAGE = str(0x410055)#0x410055
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))
However I consistently get this error.
File "C:\3_test\wifilight_py.py", line 37, in <module>
sock.sendto(str(e), (UDP_IP, UDP_PORT))
socket.error: [Errno 10013] An attempt was made to access a socket in a way forbidden by its access permissions
[Finished in 0.5s]
This despite windows firewall being disabled completely (windows 7 / Python 2.7).
I am at my wit's end, I am not sure how I should troubleshoot this. I have Wireshark installed but it provides a huge dump of information and nothing related.

Two-way communication using AF_UNIX socket

I'd like to implement the example from python official documentation on socket module using AF_UNIX socket instead of AF_INET. So here's how server code looks now:
import socket
import os
filename = '/tmp/mysock'
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
if os.path.exists(filename):
os.remove(filename)
sock.bind(filename)
while 1:
data = sock.recv(1024)
print 'Received', repr(data)
if not data:
break
sock.sendall(data)
sock.close()
When I run it, I get this:
Traceback (most recent call last):
File "/home/somecode/server.py", line 10, in <module>
data = sock.recv(2048)
socket.error: [Errno 22] Invalid argument
SOCK_STREAM is a stateful socket type, so any connection must first be acknowledged by a listening socket and then new dynamic socket (connection) is used for sending and receiving instead. You can't just receive from listening socket.
Basically you forgot to call sock.listen() on socket after binding and connection, address = sock.accept(), which blocks until a connection is established and then returns tuple with new socket (connection) and client address. Then simply use connection.recv(). This is universal for UNIX sockets and TCP/IP sockets.
For example have a look here.

Python raw socket listening for UDP packets; only half of the packets received

I am trying to create a raw socket in Python that listens for UDP packets only:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)
s.bind(('0.0.0.0', 1337))
while True:
print s.recvfrom(65535)
This needs to be run as root, and creates a raw socket on port 1337, which listens for UDP packets and prints them whenever they are received; no problems there.
Now let's make a little client to test if this works:
import socket
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
c.connect(('127.0.0.1', 1337))
c.send('message 1')
c.send('message 2')
c.send('message 3')
c.send('message 4')
c.send('message 5')
c.send('message 6')
Consistently, only the first, third, and fifth message (message 1, message 3 and message 5) will get through and be printed in the server output. The second, fourth, and sixth messages do not show up on the server output, and instead the client gets an exception:
>>> c.send('message 2')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
socket.error: [Errno 111] Connection refused
Running this in Wireshark shows that it is getting an ICMP reply for "Destination unreachable". I have been able to reproduce this on 3 distinct machines (all running Linux though). Am I missing something? Is this expected behaviour for UDP to consistently drop packets, since protocols using it are supposed to be tolerant of packet loss? Even so, why would packets be dropped when sent on the local interface?
Binding the server to 127.0.0.1 instead of 0.0.0.0 has the same result.
Solved it in kind of a silly manner; please let me know if there is another way, and I will change the accepted answer.
The solution is simply to use two sockets bound on the same port; one raw, one not raw:
import socket, select
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s1.bind(('0.0.0.0', 1337))
s2 = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)
s2.bind(('0.0.0.0', 1337))
while True:
r, w, x = select.select([s1, s2], [], [])
for i in r:
print i, i.recvfrom(131072)
This makes the "Destination unreachable" ICMP packets go away and makes all packets go through fine. I think the operating system wants a non-raw socket listening on the port for things to go well, and then any raw sockets listening on that same port will receive copies of the packets.

Categories

Resources