s.recv hang in python sockets - python-3.x

I have a client and server machine.
From client I am sending a linux command which replies after 80 sec.
As the server does not reply initial80 seconds the (s.recv) and a timeout error occurs.
Please help how to proceed here?
s= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(300)
s.connect((hostname, self.port))
s.sendall(self.msg)) # where msg is some linux command or script which replies after 80 seconds
#s.shutdown(socket.SHUT_WR)
while 1:
data = s.recv(1024)
if data == b"":
break
datai = datai + data.decode()
self.result[hostname.decode()] = datai

I couldn't reproduce it. Here's server and client code that is almost what you have - it works as desired:
client:
#!/usr/bin/env python3
import socket #for sockets
import sys #for exit
try:
#create an AF_INET, STREAM socket (TCP)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]
sys.exit();
print 'Socket Created'
host = 'localhost'
port = 8888
try:
remote_ip = socket.gethostbyname( host )
except socket.gaierror:
#could not resolve
print 'Hostname could not be resolved. Exiting'
sys.exit()
print 'Ip address of ' + host + ' is ' + remote_ip
message = "The message \n"
#Code from Stackoverflow question
#s= socket.socket(socket.AF_INET, socket.SOCK_STREAM) # this is already done
s.settimeout(300)
#Connect to remote server
#s.connect((hostname, self.port)) # different variable name
s.connect((remote_ip , port))
print 'Socket Connected to ' + host + ' on ip ' + remote_ip
s.sendall(message) # where msg is some linux command or script which replies after 80 seconds
#s.shutdown(socket.SHUT_WR)
while 1:
data = s.recv(1024)
print("Ok, I get the response :)")
if data == b"":
break
datai = "DATAI: "
datai = datai + data.decode()
#self.result[hostname.decode()] = datai
print("Datai: " + str(datai))
#End
break
s.close()
server:
#!/usr/bin/env python3
'''
Simple socket server using threads.
Taken from: https://www.binarytides.com/python-socket-server-code-example/
'''
#Code for reproduce stackoverflow question
from time import sleep
#End
import socket
import sys
HOST = '' # Symbolic name, meaning all available interfaces
PORT = 8888 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'
#Bind socket to local host and port
try:
s.bind((HOST, PORT))
except socket.error as msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
print 'Socket bind complete'
#Start listening on socket
s.listen(10)
print 'Socket now listening'
while 1:
#wait to accept a connection - blocking call
conn, addr = s.accept()
print 'Connected with ' + addr[0] + ':' + str(addr[1])
while True:
#Receiving from client
data = conn.recv(1024)
#Code for reproduce stackoverflow question
print("Waiting 80secs...")
sec = 0
while(sec < 80):
sleep(10)
sec = sec + 10
print(str(sec))
print("Ok, I'll reply...")
#End
if not data:
reply = ""
else:
reply = 'OK...' + data
conn.sendall(reply)
break
conn.close()
s.close()

Related

Application freezes after socket server starts listening for socket client connection python

Application hangs after starting up the server but the socket server was properly created. so whenever i execute a client the server response properly. Why does the application hangs? Here is the sample code
Start Button - Trigger Button
ui.button.clicked.connect(start_server) # Button to start the process
Server Socket, in here I created a thread for all the connected clients to the server then the server will broadcast it to clients
def start_server():
host = "192.168.8.241"
port = 1024
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
print("Socket created")
try:
soc.bind((host, port))
except:
print("Bind failed. Error : " + str(sys.exc_info()))
sys.exit()
soc.listen(5)
print("Socket now listening")
while True:
connection, address = soc.accept()
ip, port = soc.getsockname()
print("Connected with " + str(ip) + ":" + str(port))
try:
Thread(target=client_thread, args=(connection, ip, port)).start()
except:
print("Thread did not start.")
traceback.print_exc()
Client Thread
def client_thread(connection, ip, port, max_buffer_size = 5120):
is_active = True
while is_active:
client_input = receive_input(connection, max_buffer_size)
if "--QUIT--" in client_input:
print("Client is requesting to quit")
connection.close()
print("Connection " + str(ip) + ":" + str(port) + " closed")
is_active = False
else:
print("Processed result: {}".format(client_input))
connection.sendall(client_input)
def receive_input(connection, max_buffer_size):
client_input = connection.recv(max_buffer_size)
client_input_size = sys.getsizeof(client_input)
if client_input_size > max_buffer_size:
print("The input size is greater than expected {}".format(client_input_size))
decoded_input = client_input.decode("utf8").rstrip() # decode and strip end of line
result = process_input(decoded_input)
return result
def process_input(input_str):
print("Processing the input received from client")
return "Hello " + str(input_str).upper()
Client
def main():
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "192.168.8.241"
port = 1024
print("client_soc", soc)
try:
soc.connect((host, port))
except:
print("Connection error")
sys.exit()
print("Enter 'quit' to exit")
message = input(" -> ")
while message != 'quit':
soc.sendall(message.encode("utf8"))
while True:
data = soc.recv(1024)
print("Received response:" + str(data))
message = input(" -> ")
soc.send(b'--quit--')

Detect (non-blocking) key press while accepting client connections

I am fairly new at programming in python. I am trying to code some form of simulation using sockets. I am able connect multiple clients to the server successfully. However I would like the server to accept client connections while waiting for some input (say enter key or a string input from the console/terminal). If the user presses the enter key or enters that string, then the server should stop accepting client connections and send the list of connected clients to all clients. I know how to code the rest of the part but I dont know where to detect this key press while accepting connections. This is what I have so far. I have tried looking for similar approaches taken, but I have not found something that fits my needs.
Server File:
import socket, sys, traceback, json, pygame, curses, time
from threading import Thread
clientList = {}
def initialize():
serverConnect()
def serverConnect():
local_hostname = socket.gethostname()
host = socket.gethostbyname(local_hostname)
port = 6666
sockfd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sockfd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
sockfd.bind((host, port))
except:
print("Bind failed. Error : " + str(sys.exc_info()))
sys.exit()
sockfd.listen(3)
cid = 0
# infinite loop - do not reset for every requests
while True:
print("Awaiting client connection...")
clientSocket, address = sockfd.accept()
cid += 1
add_client_to_list(cid, address)
ip = str(address[0])
port = str(address[1])
print("Connected with " + ip + ":" + port)
try:
Thread(target=client_thread, args=(clientSocket, ip, port, cid, address)).start()
except:
print("Thread did not start.")
traceback.print_exc()
sockfd.close()
def client_thread(clientSocket, ip, port, cid, address, BUFSIZE = 5120):
clientAddress = address
clientID = cid
print("Sending client ID " + str(clientID) + " to " + ip + ":" + port)
clientSocket.sendall(str(clientID).encode("utf-8"))
threadActive = True
while threadActive:
recdData = receive_input(clientSocket, BUFSIZE)
if "--QUIT--" in recdData:
print("Client is requesting to quit")
clientSocket.close()
print("Connection " + ip + ":" + port + " closed")
threadActive = False
else:
print("\nReceived: {}".format(recdData) + " from %d" %clientID)
clientSocket.sendall("-".encode("utf8"))
def receive_input(clientSocket, BUFSIZE):
recdData = clientSocket.recv(BUFSIZE)
recdDataSize = sys.getsizeof(recdData)
if recdDataSize > BUFSIZE:
print("The input size is greater than expected {}".format(recdDataSize))
decodedData = recdData.decode("utf8").rstrip() # decode and strip end of line
result = process_input(decodedData)
return result
def process_input(input_str):
return str(input_str).upper()
def add_client_to_list(client_ID, client_address):
clientList[client_ID] = client_address
print(clientList)
def send_client_list(clientSocket, clientList):
jsonList = json.dumps(clientList)
clientSocket.sendall(str(jsonList).encode("utf-8"))
def keyPress(stdscr):
"""checking for keypress"""
stdscr.nodelay(True) # do not wait for input when calling getch
return stdscr.getch()
if __name__ == "__main__":
initialize()
Client File:
import socket
import sys
import json
def initialize():
sockfd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
port = 6666
try:
sockfd.connect((host, port))
except:
print("Connection error")
sys.exit()
# Receiving server assigned client ID
try:
myID = sockfd.recv(1024).decode("utf-8")
print("Received ID: " + myID + " from server.")
except:
print("Could not receive my ID from server")
sys.exit()
print("Enter 'quit' to exit and 'list' to receive client List")
message = input(" -> ")
while True:
if message == "list":
print("Receiving clientList from server...")
try:
jsonList = sockfd.recv(8192).decode("utf-8")
clientList = json.loads(jsonList)
print("Received list: %s" % clientList)
except:
print("Could not receive list from server")
sys.exit()
elif message != 'quit':
sockfd.sendall(message.encode("utf8"))
if sockfd.recv(5120).decode("utf8") == "-":
pass
message = input(" -> ")
else:
sockfd.send(b'--quit--')
break;
if __name__ == "__main__":
initialize()
This is what I have found. It is a small script which detects if the user inputs {a} on the console. And if he does, then a message is printed. Else it keeps listening for key presses.
import curses, time
def keyPress(stdscr):
# checking for keypress
stdscr.nodelay(True) # do not wait for input when calling getch
return stdscr.getch()
while True:
if curses.wrapper(keyPress) == 97:
print("You pressed 'a'")
else:
pass
time.sleep(0.1)
It would be great if you could guide me how I can use this concept to detect key press on the server side and stop accepting client connections and call the function to send client list to all clients. Or if you have any other approaches or suggestions.

How to reuse the socket address python?

Here is server side code:
import socket
import sys
HOST = '' # Symbolic name, meaning all available interfaces
PORT = 7800 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print ('Socket created')
#Bind socket to local host and port
try:
s.bind((HOST, PORT))
except socket.error as msg:
print ('Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
sys.exit()
print 'Socket bind complete'
#Start listening on socket
s.listen(10)
print ('Socket now listening')
#now keep talking with the client
while 1:
#wait to accept a connection - blocking call
conn, addr = s.accept()
print ('Connected with ' + addr[0] + ':' + str(addr[1]))
msg = conn.recv(1024)
s.close()
whenever I use this code for the first time I can easily connect with the client and after second time I get the error "Only one usage of each socket address (protocol/network address/port) is normally permitted"
How could I modify the code that it will work again and again?
Try this line after creating s :
# ...
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# ...
Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same across all major operating systems?

Python UDP client-server with different matching incoming-outgoing ports

Based on the example at http://www.binarytides.com/programming-udp-sockets-in-python/ I modified it to run on python 3 and used two opposed ports on client and server, so replies from each one go to these ports. Here are my examples
Server:
'''
Simple udp socket server
'''
import socket
import sys
HOST = 'localhost'
PORT_IN = 8889 # Arbitrary non-privileged port
PORT_OUT = 8888
# Datagram (udp) socket
try :
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print('Socket created')
except socket.error as e:
print(e)
sys.exit()
# Bind socket to local host and port
try:
s.bind((HOST, PORT_IN))
except socket.error as e:
print(e)
sys.exit()
print('Socket bind complete')
#now keep talking with the client
while 1:
# receive data from client (data, addr)
d = s.recvfrom(1024)
data = d[0]
addr = d[1]
if not data:
break
reply = 'OK...' + str(data)
s.sendto(reply.encode('UTF-8'), ('localhost', PORT_OUT))
print('Message[' + addr[0] + ':' + str(addr[1]) + '] - ' + str(data).strip())
s.close()
Client:
'''
udp socket client
Silver Moon
'''
import socket #for sockets
import sys #for exit
# create dgram udp socket
try:
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
except socket.error:
print('Failed to create socket')
sys.exit()
host = 'localhost'
port_out = 8889
port_in = 8888
counter = 0
while(1) :
# msg = b'aoua'
msg = 'aoua' + str(counter)
try :
#Set the whole string
s1.sendto(msg.encode('UTF-8'), (host, port_out))
# receive data from client (data, addr)
s2.bind(('localhost', port_in))
d = s2.recvfrom(1472)
reply = d[0]
addr = d[1]
print('Server reply : ' + str(reply))
except socket.error as e:
print(e)
# sys.exit()
counter += 1
Problem is with the client which cannot receive any response from server and d = s2.recvfrom(1472) hangs with error [WinError 10022] An invalid argument was supplied.
I've noticed a slightly different behaviour with sock.settimeout(seconds), but I really can't figure why. Isn't d = s2.recvfrom(buffer) supposed to wait for incoming data?
What am I missing here?
Damn... Just saw it. Silly mistake. Calling s2.bind(('localhost', port_in)) in Client inside the loop.

Python socket server that can send different data to multiple clients at the same time

I'm working on a socket based application in Python 3 that will be used to configure several raspberry pi devices from a central Python server.
I have managed to write a bit of code that allows for multiple devices to connect at the same time but I can only send data from the server on the newest connection.
Here is the code:
import socket
import sys
import threading
import time
def manageClient(conn, addr):
def Ping(conn):
count = 0
while True:
conn.send(str(count).encode())
time.sleep(1)
count += 1
print(count)
conn.send(b'Welcome to the server. Type something and hit enter\n')
threading.Thread(target = Ping, args = (conn,)).start()
while True:
data = conn.recv(1024)
print(addr[0] + ': ' + data.decode())
reply = 'OK...' + data.decode()
if not data:
break
conn.sendall(reply.encode())
print('Disconnected from ' + addr[0] + ':' + str(addr[1]))
conn.close()
def addClient():
host = '192.168.1.24'
port = 8888
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('Socket created')
try:
s.bind((host, port))
except socket.error as msg:
print('Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
sys.exit()
print('Socket bind complete')
s.listen(10)
print('Socket now listening')
while True:
conn, addr = s.accept()
print('Connected with ' + addr[0] + ':' + str(addr[1]))
threading.Thread(target = manageClient, args = (conn, addr,)).start()
s.close()
threading.Thread(target = addClient).start()
I would like to be able to have multiple users at the same time but a GUI that allows me to configure each device separately over the connection. I understand that this means coming up with a separate name for each connection but I'm not sure how I would achieve this. As of now bi directional communication does work even when multiple devices are connected I'm just unable to send unique messages to each system from the server once a new connection is established.
Thanks
Oliver.

Resources