control not returned to main thread - python

I have written a python program in which I created a UDP listener in thread 1 and trying to do something in thread 2. The issue here is control is stuck up in thread 1 and it never returns to main thread so thread 2 is not even starting up.
import threading
import socket
import time
data = ''
def ListenerUDP():
sock1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_address1 = ('localhost', 5000)
print('starting up UDP server on %s port %s' % server_address1)
sock1.bind(server_address1)
while True:
print('\nUDP server is now listening up')
data, address = sock1.recvfrom(4096)
print('received %s bytes from %s' % (len(data), address))
print('is %s' % data.hex())
def Forwarder():
print('do something')
print('Starting main thread')
t1 = threading.Thread(target=ListenerUDP)
t1.start()
t2 = threading.Thread(target=Forwarder)
t2.start()
can someone please help fixing it.

Related

Sending and receiving using sockets python

I am trying to create a function to send and receive information over a socket client & server. It appears that my code is somehow blocking. In the code the first command iteration in my for loop is carried out but then the process becomes blocked. Does anyone have any suggestions how to do this using threading or multithreading?
My code is below:
import socket
import json
import sys
import time
import select
import queue
Ni_Rio_IP= "172.22.11.2"
Ni_Base_IP= "172.22.11.1"
class AliceRio:
def __init__(self, ip_rio, ip_pc):
self.ip_rio = ip_rio
AliceRio.udp_port_rio = 60006
self.ip_pc = ip_pc
AliceRio.udp_port_pc = 50005
AliceRio.json= '{"Dest":"","Name":"","Time":"","Val":{"Str":[],"Pos":[[]],"Data":[[]]},"IP":0,"Port":0,"RT error":{"status":false,"code":0,"source":""}}'
AliceRio.dict= json.loads(self.json)
def PrintUDP(self):
print("RIO IP: %s" % self.ip_rio)
print("RIO UDP port: %s" % self.udp_port_rio)
print("PC IP: %s" % self.ip_pc)
print("PC UDP port: %s" % self.udp_port_pc)
def SendRec(self, send_str):
# Set up socket for sending
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Internet, UDP
sock.sendto(bytes(send_str, 'utf-8'), (self.ip_rio, self.udp_port_rio))
sock.close()
print('got here')
# Set up socket for receiving
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # Internet, UDP
sock.bind((self.ip_pc, self.udp_port_pc))
rec_str, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
print('got here2')
sock.close()
return rec_str
def Receive(self, rec_str):
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # Internet, UDP
sock.bind((self.ip_pc, self.udp_port_pc))
rec_str, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
sock.close()
return rec_str
def Send(self, send_str):
# Set up socket for sending
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Internet, UDP
sock.sendto(bytes(send_str, 'utf-8'), (self.ip_rio, self.udp_port_rio))
sock.close()
#return rec_str
def Aim(self, aim_perc):
if aim_perc < 0 or aim_perc > 100: return "aim_perc out of range"
send_dict=AliceRio.dict
send_dict["Dest"]='Rio'
send_dict["Name"]='Laser Control'
Laser_Mode=1
Simmer_A=0
Pulse_A= 0
Pulse_ms= 20
send_dict["Val"]["Str"]=[str(Laser_Mode), str(aim_perc), str(Simmer_A), str(Pulse_A), str(Pulse_ms)]
send_json=json.dumps(send_dict)
# send it out
self.SendRec(send_json)
rec_json= self.SendRec(send_json)
rec_dict=json.loads(rec_json)
return "Aim laser now at " + rec_dict["Val"]["Str"][1] +'%'
def PWM_Laser_Fan(self, fan_perc):
send_dict=AliceRio.dict
send_dict["Dest"]='Rio'
send_dict["Name"]='PWM Laser'
send_dict["Val"]["Str"][0]=str(fan_perc)
send_json=json.dumps(send_dict)
# send it out
rec_json= self.SendRec(send_json)
rec_dict=json.loads(rec_json)
return rec_dict["Val"]["Str"][0]
def Poll(self):
send_dict=AliceRio.dict
send_dict["Dest"]='Rio'
send_dict["Name"]='Poll'
send_json=json.dumps(send_dict)
# send it out
rec_json= self.SendRec(send_json)
rec_dict=json.loads(rec_json)
if rec_dict["Val"]["Data"][0][0]==0: pid_mode='off'
else: pid_mode='PID'
print('PID mode:', pid_mode)
print('Pos X:', rec_dict["Val"]["Data"][0][1])
print('Pos Y:', rec_dict["Val"]["Data"][0][2])
print('Home:', rec_dict["Val"]["Data"][0][3])
print('Enabled:', rec_dict["Val"]["Data"][0][4])
def PIDControl(self, pid_mode,pid_center):
if pid_mode=="off": mode= 0
elif pid_mode=="PID":mode =1
else: return "pid_mode not valid"
if pid_center[0] not in range(-2048,2048): return "center x-pos not in range"
if pid_center[1] not in range(-2048,2048): return "center y-pos not in range"
send_dict=AliceRio.dict
send_dict["Dest"]='Rio'
send_dict["Name"]='PID Control'
send_dict["Val"]["Str"]=[str(mode), str(pid_center[0]), str(pid_center[1])]
send_json=json.dumps(send_dict)
# send it out
rec_json= self.SendRec(send_json)
rec_dict=json.loads(rec_json)
return "PID mode now at " + rec_dict["Val"]["Str"][0]
Alice1 = AliceRio(Ni_Rio_IP, Ni_Base_IP)
Alice1.PrintUDP()
for i in range(10):
Alice1.Aim((i*10)+10)
time.sleep(0.2)
I would suggest learning to use Pdb and trace through the execution of your program to find where it is getting caught.
Also when learning/developing with sockets I've found that it helps to have separate programs for your client and server in the beginning so you can see how both sides are handling exchanges instead of going the threading route to start since the logging can get confusing, best of luck!
Module threading does help in this scenario.
We can create a thread to receiving incoming messages. And when new message received the thread trigger an event to notify the waiting method SendRec.
import sys
import socket
import json
import threading
import time
class AliceRio:
def __init__(self, .....):
# .........
self.s_in = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.s_in.bind((self.ip_pc, self.udp_port_pc))
self.evt = threading.Event()
self.last_msg = None
def _recv(self):
while True:
msg, _ = self.s_in.recvfrom(1024)
self.last_msg = msg
self.evt.set()
def SendRec(self, send_str):
if not hasattr(self, 'th_recv'):
th = threading.Thread(target=self._recv)
th.setDaemon(True)
th.start()
self.th_recv = th
self.evt.clear()
rio_endpoint = (self.ip_rio, self.udp_port_rio)
s_out = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s_out.sendto(bytes(send_str, 'utf-8'), rio_endpoint)
s_out.close()
if self.evt.wait(timeout=15.0) and self.last_msg:
return self.last_msg
raise Exception('timeout waiting for response.')

Python tcp server with multithreading can not print return value from thread

I am trying to set up a tcp server in Python using Multithreading. The problem is that the queue only return data from only one thread. That means it only prints the data from the thread created with 5555 or 5556. I confirmed both data reaches port by connecting one device per time but it does not print the result from connection to the other port when more than one device connected.
Thanks for your help.
#!usr/bin/python
from threading import Thread
import socket
import sys
from queue import Queue
def clientthread(conn,q):
buffer=""
data = conn.recv(8192)
buffer=data
q.put(buffer)
return buffer
def main():
try:
host = '169.254.162.144'
port = 5555
tot_socket =2
list_sock = []
conarr=[]
threads=[]
for i in range(tot_socket):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind((host, port+i))
s.listen(10)
list_sock.append(s)
print ("[*] Server listening on %s %d" %(host, (port+i)))
for j in range(len(list_sock)):
conn, addr = list_sock[j].accept()
conarr.append(conn)
print('[*] Connected with ' + addr[0] + ':' + str(addr[1]))
while 1:
queue1 = Queue()
for j in range(len(list_sock)):
thread =Thread( target=clientthread, args=(conn, queue1) )
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
while not queue1.empty():
result = queue1.get()
print(result)
threads=[]
s.close()
except KeyboardInterrupt as msg:
sys.exit(0)
if __name__ == "__main__":
main()

Stop a python script from executing

I have the below python script(server.py) in order to listen to a port and capture the requests from the client. I am calling this script from another python file(Main.py). My requirement is to stop executing server.py after certain amount of time. I tried using exit() at the last line of the file - server.py to stop the server and stop the execution of the file, however I was not able to stop the script from running and the server kept responding. Can anyone help me in letting me know where I am going wrong.
Server.py
bind_ip = "127.0.0.1"
bind_port = 2530
def servercreate():
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((bind_ip,bind_port))
server.listen(5)
while True:
client, addr = server.accept()
print('[*] Accepted connection from: %s:%d' % (addr[0], addr[1]))
client_handler = threading.Thread(target=handle_client, args=(client,))
client_handler.start()
def handle_client(client_socket):
request = client_socket.recv(2056)
print('[*] Received: %s' % request)
message = "{}"
client_socket.send(message.encode('utf-8'))
client_socket.close()
if __name__ == '__main__':
servercreate()
Main.py
import Server
Server.servercreate()
if you don't want your code interrupted by time.sleep (which I think stops the code from running), use this:
import time
timeout = time.time() + 10
while True:
print ('hello')
if time.time() > timeout:
print ('program terminated')
break
if you want 10 minutes worth of time use:
timeout = time.time() + 60*10
If you just want to stop the program running after a certain amount of time use something like
import time
x=0
while True:
print ('waiting 5')
time.sleep(5)
x += 1
if x == (10):
break
the time.sleep is in seconds, break stops the loop and should end your program
update, try this:
import time
bind_ip = "127.0.0.1"
bind_port = 2530
def servercreate():
#put minutes of time you want program to run for below
minutes = 10
timeout = time.time() + (60*minutes)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((bind_ip,bind_port))
server.listen(5)
while True:
client, addr = server.accept()
print('[*] Accepted connection from: %s:%d' % (addr[0], addr[1]))
client_handler = threading.Thread(target=handle_client, args=(client,))
client_handler.start()
if time.time() > timeout:
break
def handle_client(client_socket):
request = client_socket.recv(2056)
print('[*] Received: %s' % request)
message = "{}"
client_socket.send(message.encode('utf-8'))
client_socket.close()
if __name__ == '__main__':
servercreate()

What's the wrong with udp code in Python?

I hope to receive 300*3 = 900 of messages at "192.168.1.114" in multi thread case, but 876 messages arrived. however, it can all arrived by single thread. and it also can all arrived by sendto '127.0.0.1'.
Is it because of the reasons for UDP?
import socket
import threading
from time import sleep
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
host = '192.168.1.114'
port = 9999
def sendMsg(args):
msg = 'thread %06d - 1' % args
s.sendto(msg, (host, port))
sleep(1)
msg = 'thread %06d - 2' % args
s.sendto(msg, (host, port))
sleep(1)
msg = 'thread %06d - 3' % args
s.sendto(msg, (host, port))
threads = []
for i in range(300):
t = threading.Thread(target=sendMsg, args=(i,))
threads.append(t)
t.start()
for j in threads:
j.join()
s.close()

How do I allow more simultaneous socket connections?

I'm attempting to implement the Reactor pattern in Python. I think I have a pretty decent start using multiprocessing and select.select. However, I'm trying to stress-test my server, so I wrote a simple DoS client to flood it with connections. But I get an interesting error:
[WinError 10061] No connection could be made because the target machine actively refused it
The interesting thing about this is that I'm doing socket.listen(5) for the backlog amount on the server. After I get readers ready from select.select I display the count, and I only ever have 1 or 2 - not the 5 that I would expect.
For a small number of threads (~20) I haven't noticed it choke, but for a larger number (50+) it does tend to refuse connections.
Is my problem on the server or client side (or just at the OS/socket level)? Is this a problem that I can fix? And if so, how?
Here is my code:
Client
import threading
import time
import socket
from contextlib import contextmanager
IP = '127.0.0.1'
PORT = 4200
#contextmanager
def open_socket(ip, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((ip, port))
yield sock
finally:
sock.close()
class Flood(threading.Thread):
def __init__(self, id):
super(Flood, self).__init__()
self.id = id
self.failed = False
def run(self):
try:
with open_socket(IP, PORT) as sock:
msg = "Hello this is some data from %d" % self.id
sock.send(msg.encode())
except Exception as e:
print(e)
self.failed = True
def make_threads(count):
return [Flood(_) for _ in range(count)]
threads = make_threads(5000)
start = time.time()
for t in threads:
t.start()
for t in threads:
t.join()
print("Failed: ", sum(1 if x.failed else 0 for x in threads))
print("Done in %f seconds" % (time.time() - start))
Server
import sys
import logging
import socket
import select
import time
import queue
from multiprocessing import Process, Queue, Value
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
log.addHandler(logging.StreamHandler())
IP = '127.0.0.1'
PORT = 4200
keep_running = True
def dispatcher(q, keeprunning):
try:
while keeprunning:
val = None
try:
val = q.get(True, 5)
if val:
log.debug(val[0].recv(1024).decode())
val[0].shutdown(socket.SHUT_RDWR)
val[0].close()
except queue.Empty:
pass
log.debug("Dispatcher quitting")
except KeyboardInterrupt:
log.debug("^C caught, dispatcher quitting")
def mainloop(sock):
readers, writers, errors = [sock], [], []
timeout = 5
while True:
readers, writers, errors = select.select(readers,
writers,
errors,
timeout)
incoming = yield readers, writers, errors
if incoming and len(incoming) == 3:
readers, writers, errors = incoming
if not readers:
readers.append(sock)
def run_server():
keeprunning = Value('b', True)
q = Queue()
p = Process(target=dispatcher, args=(q, keep_running))
try:
p.start()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((IP, PORT))
sock.listen(50)
sock.setblocking(0)
loop = mainloop(sock)
for readers, writers, errors in loop:
if readers:
client, addr = readers[0].accept()
q.put((client, addr))
log.debug('*'*50)
log.debug('%d Readers', len(readers))
log.debug('%d Writers', len(writers))
log.debug('%d Errors', len(errors))
except KeyboardInterrupt:
log.info("^C caught, shutting down...")
finally:
keeprunning.value = False
sock.close()
p.join()
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: test.py (client|server)")
elif sys.argv[1] == 'client':
run_client()
elif sys.argv[1] == 'server':
run_server()
I tried to test your code, but failed on import queue.
Nevertheless, it might be that
your OS acts as the listen() function is specified: "Implementations may impose a limit on backlog and silently reduce the specified value."
your OS stops accepting the connection as soon there are enough incomplete connections, which might not be displayed upon request.
These are just guesses about what might be the reason; maybe I am completely wrong.

Categories