I want to send some data to a sensor and if the python script doesn't receive the data I want the receive function to timeout and resend the data.
def subscribe():
UDP_IP = "192.168.1.166"
UDP_PORT = 10000
MESSAGE = '6864001e636caccf2393730420202020202004739323cfac202020202020'.decode('hex')
print "UDP target IP:", UDP_IP
print "UDP target port:", UDP_PORT
print "message:", MESSAGE
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))
recieve_data = recieve()
if recieve_data == subscribe_recieve_on or recieve_data == subscribe_recieve_off:
logging.info('Subscribition to light successful')
else:
logging.info('Subscribition to light unsuccessful')
def recieve():
UDP_IP = "192.168.1.118"
UDP_PORT = 10000
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))
data, addr = sock.recvfrom(1024)
return data.encode('hex')
subscribe()
At the moment it gets stuck in the receive function if it doesn't receive any data:
data, addr = sock.recvfrom(1024)
However I want it to timeout after e.g. 2 seconds and rerun the subscribe() function.
I've tried using a while true statement with a timeout and try/exception however I get a port currently in use even when closing the port. Also feel this way is messy.
Any ideas would be appreciated.
You get the "currently in use" exception because you are recreating the sockets every time you call either of those functions, without closing them first.
Try creating the sockets beforehand. The response might come before the receiving socket is created in which case the packet is just going to be rejected.
Then you should try only the sendto-recvfrom calls in a loop.
Also you either need to set a timeout with settimeout on the receiving socket so it does not get blocked then catch the timeout exception or use a polling mechanism like select or poll to check whether you have received any data.
Related
Im trying to send a messages from the server to the client
I tried deleting the .close and puting a while loop on print but it still doesn't won't to work
Client
import socket
s = socket.socket()
host = socket.gethostname()
port = 12345
s.connect((host, port))
while True:
print (s.recv(1024))
Server
import socket
s = socket.socket()
host = socket.gethostname()
port = 12345
s.bind((host, port))
s.listen(5)
while True:
c, addr = s.accept()
print ('Got connection from', addr)
x = str(input("ënter a message"))
data = x.encode()
c.send(data)
I expect the output to be 2 messages from the server but it is only sending 1 and then closing the connection
Switch your accept and while True: lines. Once you accept a connection, keep sending on the same connection.
Note that TCP is a streaming protocol. There is no concept of "messages", but just a bunch of bytes. If you send fast enough, such as:
c.send(b'abc')
c.send(b'def')
then recv(1024) could receive b'abcdef'. For more complex communication, you'll have to define a protocol and buffer recv until you are sure you have a complete message. A simple way in this case is read until you find a newline, or send a byte (or more) indicating the size of the total message before sending the actual message.
I am building a simple network chat in Python using UDP, however, when I run the server code on one machine and the client on another, no message is received by the server and no message is sent back to the client by the server script. Here is my code:
Server:
import socket, sys
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('', 9997)) #need higher port
while True:
x = raw_input("Enter your message: ")
sent = sock.sendto(x, ('', 9997))
data, address = sock.recvfrom(4096)
print data, " ", address
sock.close()
Client:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
print "Waiting to receive"
data, server = sock.recvfrom(4096)
print data
x = raw_input("Enter message: ")
sent = sock.sendto(x, server)
sock.close()
Does anyone know what I am doing wrong here? Is is possible that code is fine, but the UDP is not reliable enough and is dropping the message?
As I said, since your code seems a little unclear (to me, at least), I'm posting you a very similar working example.
Here's the Server:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_address = ('localhost', 1932)
sock.bind(server_address)
BUFFER_SIZE = 4096
try:
while True:
data, address = sock.recvfrom(BUFFER_SIZE)
print "Client sends: ", data
reply = raw_input("Your response:\n")
sock.sendto(reply,address)
except KeyboardInterrupt:
sock.close()
The server creates a socket and binds it to its address and the port it's listening to, 1932 in our case. He waits for an incoming message, asks for a reply, then sends it back to the sender.
Here's the Client:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client_address = ('localhost', 1931)
server_address = ('localhost', 1932)
sock.bind(client_address)
BUFFER_SIZE = 4096
try:
first_msg = raw_input("Your first message:\n")
sock.sendto(first_msg,server_address)
while True:
data, address = sock.recvfrom(BUFFER_SIZE)
print "Client sends: ", data
reply = raw_input("Your response:\n")
sock.sendto(reply,address)
except KeyboardInterrupt:
sock.close()
It's very similar to the server, the only difference is that it sends a message before the while loop, in order to start the conversation. Then it just enters the receive/reply loop, just as the server does. It has the server address too, that is different (different port, since I'm on localhost)
The try/catch block is here just to close gracefully the whole process.
I used localhost and different ports on my computer and tested it, and it works. You should just change the addresses to get it working over LAN, and you could keep the same port if the addresses are different, it should work.
I'm developing a reverse shell application in python, and right now I'm trying to implement an autodiscovery feature. It should work as follows:
The server broadcasts the IP/port it listens for connections on, and waits for a client. If no client tries to connect in a few seconds, it broadcasts again (and repeat till a connection).
The client tries to receive the broadcast of the server, and connects to the advertised IP/port.
The broadcast works fine, the client receives the IP/port and successfully connects, however after using the connected pair of ports I get (server side):
socket.error: [Errno 35] Resource temporarily unavailable
Server side test code:
sckt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sckt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sckt.settimeout(2)
sckt.bind(('', 9999))
sckt.listen(5)
broadcastSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
broadcastSocket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
broadcastSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
while True:
broadcastSocket.sendto(socket.gethostbyname(socket.getfqdn()) + ' ' + str(9999), ('<broadcast>', 8888))
try:
sock, address = sckt.accept()
break
except socket.timeout:
pass
broadcastSocket.close()
sckt.settimeout(None)
sock.send('test')
# if I add time.sleep(1) here, it works, but I don't get why
# would sock be unavailable at first, but available a second later
print sock.recv(1) # this is where it fails
# note that it also fails with any recv buffer size, for instance 1024
Why on earth would I want to receive 1 byte of data, you might ask. I have an algorithm which prefixes messages with their lengths, and the receiver reads this prefix byte-by-byte till a delimiter, thats why.
Client side test code:
broadcastSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
broadcastSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
broadcastSocket.settimeout(3)
broadcastSocket.bind(('', 8888))
while True:
try:
data = broadcastSocket.recv(1024)
break
except socket.timeout:
pass
broadcastSocket.close()
sckt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sckt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sckt.connect((str(data.split()[0]), int(data.split()[1])))
print sckt.recv(1024)
sckt.send('lel')
If I omit the whole broadcast and autodiscovery part of the code and simply manually enter the IP/port of the server print sock.recv(1) doesn't fail.
Any clues on what the issue might be?
Change sckt.settimeout(None) to sock.settimout(None) in the server code.
You want to have the accepted socket in blocking mode and not the accepting one.
This ensures that the sckt.recv waits for an incoming message from the client.
P.S.
sock.setblocking(1) is exactly the same
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").
I'm writing a multithreaded distributed networking algorithm.
I've one thread that listens to new connections. Every time a new connection is established a separate thread is started for listening to messages from that connection.
My problem is that the socket I open works perfectly in both directions inside the connection listener. After I pass the socket object for that connection to the message listener I can read data from the socket, but sending data through it doesn't reach the remote host.
Here's the essential snip from my code:
def connection_listener(port, start_e, terminate_e):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.settimeout(1)
s.bind(('', port))
s.listen(1)
while (not start_e.isSet()):
try:
conn, addr = s.accept()
msg_in = conn.recv(1024).split(":")
if (msg_in[1]=="hello"):
# If addr sends us a 'id:hello', we reply with a 'my_id:welcome'
conn.send(str(my_id)+":welcome")
t = Thread(target=message_listener, args=(conn, addr[0], terminate_e, ))
t.start()
except:
pass # timeout
def message_listener(conn, address, terminate_e):
while (not terminate_e.isSet()):
try:
msg_in = conn.recv(1024)
# Here I can receive everything that I send from the other end of conn,
# but conn.send("any data") doesn't reach the remote host
What I'd like to do is send acknowledgement-like messages from the message listener thread using the conn. Is this possible somehow or am I thinking and doing it wrong?
I sorted this out myself, so I'll share my answer.
I made the protocol exchange fixed size messages by padding with zeroes up to the desired length. I used a length of 32 bytes, which might be quite tiny from the hardware's point of view. Nevertheless it seems to work as supposed.
Pragmatically my solution looks like:
def send_everyone(message):
for i in range(len(peers)):
chunk = (str(my_id)+":"+message).rjust(32, '0')
peers[i].send(chunk)
And on the receiving side we want only 32 bytes at a time:
def message_listener(conn, address, terminate_e):
while (not terminate_e.isSet()):
try:
msg_in = conn.recv(32)
...