I am trying to get a time out on the code below. But it just hangs at the recv and never times out. Can someone point to what I am doing wrong? I have looked and I can't seem to find too much on it.
import socket
host = "localhost"
port = 8888
# create socket object
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# give object the ip and port to listen on
server_address = (host, port)
print('starting up on %s port %s' % server_address)
sock.bind(server_address)
# how many listeners
sock.listen(0)
# sets the time out
sock.settimeout(10)
while True:
print('waiting for a connection')
try:
#this waits for a connection from the sending side.
connection, client_address = sock.accept()
print('connection from', client_address)
start = False
message = ""
while client_address != "":
#this listens and waits for data to be sent and sets it to the data variable
data = connection.recv(32000).decode()
You have set an accept timeout on the listening socket, not a read timeout on the receiving socket.
Related
Consider the following python script:
import socket
import time
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('0.0.0.0', 9999))
s.listen()
connections = []
while True:
time.sleep(1)
conn, addr = s.accept()
connections.append(conn)
# send and receive data using open connections
According to the socket documentation:
socket.accept()
Accept a connection. The socket must be bound to an
address and listening for connections. The return value is a pair
(conn, address) where conn is a new socket object usable to send and
receive data on the connection, and address is the address bound to
the socket on the other end of the connection.
Now suppose I want to change the socket options, like:
setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2048)
Should I call this method on the original socket s, the new connection conn or both of them?
I have setup a tcp socket between a client and a server, very basic. Client side:
#!/usr/bin/env python3
import socket
# create a socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# get local machine name
host = "81.88.95.250"
port = 25000
# connection to hostname on the port.
s.connect((host, port))
# Receive no more than 1024 bytes
msg = s.recv(1024)
s.close()
print (msg.decode('ascii'))
server side:
#!/usr/bin/env python3
import socket
# create a socket object
serversocket = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
# get local machine name
host = socket.gethostname()
port = 25000
# bind to the port
serversocket.bind((host, port))
# queue up to 5 requests
serversocket.listen(5)
while True:
# establish a connection
clientsocket,addr = serversocket.accept()
print("Got a connection from %s" % str(addr))
msg = 'Thank you for connecting'+ "\r\n"
clientsocket.send(msg.encode('ascii'))
clientsocket.close()
My target is to send notification from client to server, and that's easy. The difficult part is that I also need in some circumstances to start the connection from the server and to send a command to the client and this must be executed as soon as it is received, so I cannot setup a periodic "poll". But I'm quite confused on this part, because the client is behind a NAT, not exposed with a public IP.
I have a working command for linux that sends a request and gets a response:
echo -n -e '\x9e\x4c\x23\x00\x00\xff\xff\xce\xf2\x3b\x18\x80' | nc -u -w 1 -p 11244 127.0.0.1 11235
I'm trying to do the same through the python:
import socket
IP = "127.0.0.1"
PORT = 11235
MESSAGE = "9e4c230000ffffcef23b1880"
BINARY_MESSAGE = MESSAGE.decode('hex')
print ("BINARY_MESSAGE: [%s]" % BINARY_MESSAGE) # <- message is the same as echo -en does
srvsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srvsock.settimeout(3) # 3 seconds
srvsock.connect((IP, PORT))
srvsock.sendall(BINARY_MESSAGE)
data = srvsock.recv(4096)
print ("Received message: [%s]" % data)
srvsock.close()
I receive a blank responce:
BINARY_MESSAGE: [�L#����;�]
Received message: []
I guess I'm doing something wrong.
Your nc command line is using UDP (-u). Your Python code is using TCP (socket.SOCK_STREAM). You want to create a UDP socket:
srvsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
You will want to get rid of the call to connect, but you will need a call bind if you expect to receive messages on that socket. For example, the following code sends a message then waits for a reply on the same socket:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('127.0.0.1', 2222))
s.sendto('this is a test', ('127.0.0.1', 3333))
data, srcaddr = s.recvfrom(1024)
print(data, srcaddr)
Remember that UDP is a connectionless protocol. The other side of this conversation can't "reply" to the message; it needs to explicitly send to the address/port on which the above code is listening. In Python the other side of this conversation might look like:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('127.0.0.1', 3333))
data, srcaddr = s.recvfrom(1024)
print(data)
s.sendto('that was a test', srcaddr)
The above code waits for a message then sends a response back.
I'm working with 3 raspberry pi, one as a server and the two others are clients. What I want to do is to make the clients communicate with the server simultaneously, I don't want to wait for client1 communication to be done in order to launch client2 request to the server (which I succeeded to do). However, I want each client to send different data to server at the same time. I tried to use Sockets and threading, like below.
server code:
import socket
import RPi.GPIO as GPIO
from threading import Thread
# Multithreaded Python server : TCP Server Socket Thread Pool
class ClientThread(Thread):
def __init__(self,ip,port):
Thread.__init__(self)
self.ip = ip
self.port = port
print ("[+] New server socket thread started for " + ip + ":" + str(port))
def run(self):
while True :
data = conn.recv(2048)
data = data.decode('utf-8')
print ("Server received data:", data)
MESSAGE = input("Multithreaded Python server : Enter Response from Server/Enter exit:")
if MESSAGE == 'exit':
break
conn.send(str.encode(MESSAGE)) # echo
# Multithreaded Python server : TCP Server Socket Program Stub
TCP_IP = ''
TCP_PORT = 9050
BUFFER_SIZE = 2000 # Usually 1024, but we need quick response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(2)
threads = []
list_data=[]
while True:
print ("Multithreaded Python server : Waiting for connections from TCP clients...")
(conn, (ip,port)) = s.accept()
data = conn.recv(2048)
newthread = ClientThread(ip,port)
newthread.start()
threads.append(newthread)
list_data.append(data)
for t in threads:
t.join()
client1 code:
import socket
import RPi.GPIO as GPIO
import time
host = '192.168.0.198'
port = 9050
BUFFER_SIZE = 2000
MESSAGE = input("tcpClient1: Enter message/ Enter exit:")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
while MESSAGE != 'exit':
s.send(str.encode(MESSAGE))
data = s.recv(BUFFER_SIZE)
data = data.decode('utf-8')
print (" Client2 received data:", data)
MESSAGE = input("tcpClient2: Enter message to continue/ Enter exit:")
client2 code:
import socket
import RPi.GPIO as GPIO
import time
import socket
host = '192.168.0.198'
port = 9050
BUFFER_SIZE = 2000
MESSAGE = input("tcpClient2: Enter message/ Enter exit:")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
while MESSAGE != 'exit':
s.send(str.encode(MESSAGE))
data = s.recv(BUFFER_SIZE)
data = data.decode('utf-8')
print (" Client received data:", data)
MESSAGE = input("tcpClient2: Enter message to continue/ Enter exit:")
when i run, i obtain:
in the server terminal:
Multithreaded Python server : Waiting for connections from TCP clients...
[+] New server socket thread started for 192.168.0.197:47012
Multithreaded Python server : Waiting for connections from TCP clients...
[+] New server socket thread started for 192.168.0.196:47886
Multithreaded Python server : Waiting for connections from TCP clients...
in client1 terminal:
tcpClient1: Enter message/ Enter exit:begin
in client2 terminal:
tcpClient2: Enter message/ Enter exit:begin
It seems like server didn't receive or send any data.
As #Hikke mentioned in his comment, your server receives at two different places. The conn.recv call in this code snippet eats up the data that the server receiving thread is expecting. Remove data = conn.recv(2048) in your server's main loop:
while True:
print ("Multithreaded Python server : Waiting for connections from TCP clients...")
(conn, (ip,port)) = s.accept()
data = conn.recv(2048) # <== dont eat the data of your thread here!
newthread = ClientThread(ip,port)
newthread.start()
threads.append(newthread)
list_data.append(data)
I wrote a basic server-client scripts using sockets, and everything works fine on my LAN, but it doesnt work when im trying to connect to the client thats not in my LAN. I also port forwarded these ports
this is server
###SERVER####
def ChatConnection():
print('Waiting for a connection...\n')
SOCKET = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
SOCKET.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
HOST = ''
PORT = 8989
SOCKET.bind((HOST, PORT))
SOCKET.listen(1)
CONN, ADDR = SOCKET.accept()
print('You can now chat')
while True:
MSG = str(input('\n[YOU]> '))
while not MSG: MSG = str(input('\n[YOU]> '))
CONN.send(MSG.encode())
print('\nAwaiting reply...')
REPLY = CONN.recv(4096).decode()
CONN.close()
this is client
###CLIENT###
def ChatConnection():
print('Waiting for a connection...\n')
while True:
try:
HOST = SERVER EXTERNAL IP
PORT = 8989
SOCKET = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
SOCKET.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
SOCKET.connect((HOST, PORT))
print('You can now chat with server')
print('\nWaiting for server...')
while True:
REPLY = SOCKET.recv(4096)
print('\n[USER]> %s'%REPLY.decode())
MSG = str(input('\n[YOU]> '))
while not MSG: MSG = str(input('\n[YOU]> '))
SOCKET.send(MSG.encode())
print('\nAwaiting reply...')
SOCKET.close()
except Exception: pass
what i need to do so this will work on the WAN?
Make sure that port forward WORKS, to check this run your program and try running a port scan on your public IP.Port scanning tool
Try to change the HOST to 0.0.0.0.
If that didn't work go to CMD and write netstat -a while your script is running.
Search for the port you are listening on and make sure the IP is 0.0.0.0.
If the IP is 0.0.0.0 then try to turn off your Firewall.