Socket receiving in while 1 - python

I'm trying to create socket connections in python. I need to listen to server until it sends a message, thus I need to use while True.
Client:
import RPi.GPIO as GPIO
import time
import socket
GPIO.setmode(GPIO.BOARD)
pinLDR = 7
pinLED = 11
touch = False
sock = socket.socket()
sock.connect(('192.168.1.67', 9092))
while True:
print sock.recv(256)
def rc_time ():
count = 0
GPIO.setup(pinLDR, GPIO.OUT)
GPIO.output(pinLDR, GPIO.LOW)
time.sleep(0.1)
GPIO.setup(pinLDR, GPIO.IN)
while (GPIO.input(pinLDR) == GPIO.LOW):
count += 1
return count
def led(lh):
GPIO.setup(pinLED, GPIO.OUT)
if lh == 1:
GPIO.output(pinLED, GPIO.HIGH)
else:
GPIO.output(pinLED, GPIO.LOW)
try:
while True:
print(str(rc_time()))
if rc_time() > 5000:
if touch == False:
print "triggered"
sock.send("triggered")
touch = True
else:
if touch == True:
sock.send("nottriggered")
print "nottriggered"
touch = False
except KeyboardInterrupt:
pass
finally:
GPIO.cleanup()
sock.close()
But I have a problem with it. Nothing is printed even if a server sends a message. And the whole code after first while True doesn't work

UPDATE: The issue with the code in the question is that it has an infinite loop at the top. None of the code below this will ever execute:
while True:
print sock.recv(256)
(And apparently this particular server doesn't send a message until it's received one first, so it will never send anything.)
Here's a simple working example. If this doesn't help, you'll need to provide more context in your question.
Here's the client:
import socket
s = socket.socket()
s.connect(('localhost', 12345))
while True:
print s.recv(256)
Corresponding server code:
import socket
import time
s = socket.socket()
s.bind(('', 12345))
s.listen(0)
conn, addr = s.accept()
while True:
conn.send("Hello")
time.sleep(10)

Related

Connect sql server to Python3 - client-server

i'm new in socket programming with python i wrote some code for client and server that is not completed.
i want to connect my server side to Sql server dbms to store data there (this is a student management system) i want to send some data from client side then server side store them on data base and when got asked by client return them.
Here is my both side codes:
this is client:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host ="127.0.0.1"
port =8000
def send(message):
message=str(message)
s.send(message.encode())
data = s.recv(1024).decode()
print (data)
def end():
s.close ()
def menu1():
print("Data has been saved to DB!\nWhat you need next?\n1.Close Connection.\n2.Enter More Data.\n3.Get Data.")
while 1:
m=input()
if int(m)==1:
end()
elif int(m)==2:
enter_data()
elif int(m)==3:
get_data()
else:
print("Choose a Num between 1-3!\n")
def enter_data():
flag=0
while 1:
if flag==0:
r = input('enter amount of student: ')
for i in range (0,int(r)):
name=input("Enter Student %d name"%(i))
send(name)
break
menu1()
def start():
s.connect((host,port))
print("You are connected to server!")
print("1.Enter Data")
print("2.Get Data")
m=input()
if int(m)==1:
enter_data()
elif int(m)==2:
end()
def menu():
m = input("press any key to connect!\n");
start()
if __name__ == "__main__":
menu()
and this is server side code:
import socket
from threading import *
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = ""
port = 8000
#print (host)
#print (port)
serversocket.bind((host, port))
class client(Thread):
def __init__(self, socket, address):
Thread.__init__(self)
self.sock = socket
self.addr = address
self.start()
def run(self):
#amount=self.sock.recv(1024).decode()
#amount=int(amount)
#counter=0
while 1:
api=self.sock.recv(1024).decode()
#print(self.sock.recv(1024).decode())
print("Client sent some messages: %s"%(api))
#api=self.sock.recv(1024).decode()
if str(api)=="avarage":
avarage=2/10
c=str(avarage)
self.sock.send(c.encode())
else:
avarage = 3 / 10
c = str(avarage)
self.sock.send(c.encode())
serversocket.listen(5)
print ("server started and listening to port:%s"%(port))
while 1:
clientsocket, address = serversocket.accept()
client(clientsocket, address)
I'm a bit new in this type of programming so please give me a part of code that i need to add.
thanks in advance.
I know that some parts of this code is not usable i just wrote them for test some things and get the concept of that.
also when i want to close connection server side i got this error:
File "C:/Users/name/PycharmProjects/Socket/venv/Socket1.py", line 23, in run
api=self.sock.recv(1024).decode()
ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine

Multithreading does not work for bi-directional udp communication python

Output at console server
I am trying to write bi-directional UDP communication using multithread but it crashes after sending two messages. Also i am new to threading so please post your solution on this.
Thanks
Server side:
import threading
from threading import Thread
import socket
from socket import *
import time
import pymongo
from datetime import datetime
from time import ctime
#broadcast works for this program
import netifaces
import os
import re
import struct
class cont():
def get_msg(self):
UDP = "192.168.1.27"
port = 4343
address = UDP, port
self.sock = socket(AF_INET, SOCK_DGRAM)
self.sock.bind(address)
while True:
r = self.sock.recvfrom(1000)
print("controller1: %s" % (r[0]))
reply = input('Main controller : ')
client_address = r[1]
self.sock.sendto(bytearray(reply, "utf-8"), client_address)
t2 = threading.Thread(target=self.get_msg, args=(reply,))
t2.start()
if __name__=='__main__':
c=cont()
#c.broad(msg="")
c.get_msg()
Client side:
UDP=""
port=4343
address=UDP,port
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while(True):
msg=input("Controller1")
client.sendto(bytearray(msg,"utf-8"),address)
reply=client.recvfrom(1000)
recved=str(reply)
print("Main Controller:% s" % recved))
Output required :
Server Console:
Client:b'hello'
Server:b'hi
Client Console:
Client: b'hello'
Server : (b'hi',('ip',port)
Here is a TCP class I made for communicating with my robots, can be easily modified for UDP. Might seem like a lot of code, but it's what it takes for "reliable" "two way" communication, without blocking your main program. I use processes instead of threads because threads in python aren't "real" threads due to the global interpreter lock.
import socket
from multiprocessing import Process, Queue, Event, Value
import traceback
class SocketComm(object):
def __init__(self,port):
self.address = ""
self.otherAddress = object
self.port = port
self.finished = Value("b", True)
self.inbox = Queue()
self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.getMessagesProcess = Process(target=self.getMessages)
self.getMessagesProcess._stop_event = Event()
self.getMessagesProcess.daemon = True
self.connected = False
self.timeout = 3
return
def setupLine(self, addr):
self.address = addr
if self.address is "": #i.e. server on raspberry pi
try:
self.connection.settimeout(self.timeout)
self.connection.bind((self.address, self.port))
print("binding with port: " + str(self.port))
self.connection.listen(1)
self.connection, self.otherAddress = self.connection.accept()
print("connected to client at: " + self.otherAddress[0])
except socket.error as e:
print(str(e))
return False
else:
try:
#print("connecting to port: " + str(self.port))
self.connection.connect((self.address, self.port)) # i.e. client
print("connected to server")
except socket.error as e:
#print(str(e))
return False
self.getMessagesProcess.start()
self.connected = True
self.finished.value = False
print("inbox at: " + str(id(self.inbox)))
return True
def sendMessage(self, msg):
try:
self.connection.send(str.encode(msg))
#print("sent: " + str(msg))
except Exception as e:
pass
#print(str(e))
#traceback.print_exc()
#print("exception caught.")
return
def getMessages(self):
#print("getting messages now")
self.connection.settimeout(1)
while(not self.finished.value):
#print("checking inbox")
#print("inbox length: " + str(len(self.inbox)))
try:
received = self.connection.recv(1024)
decoded = received.decode('utf-8')
if len(decoded) > 0:
if(decoded == "end"):
self.finished.value = True
else:
self.inbox.put(decoded)
print("received: " + str(decoded))
except socket.error as e:
if(type(e).__name__ == "timeout"):
pass
else:
print("endpoint closed.")
self.finished.value = True
return
def closeConnection(self):
if(self.connected):
self.finished.value = True
self.getMessagesProcess._stop_event.set()
self.sendMessage("end")
try:
self.getMessagesProcess.join()
except:
print("process already finished.")
self.connection.close()
return
##
##if(__name__ == "__main__"):
## robotClient = SocketComm(5555)
## robotClient.setupLine("127.0.0.1")
## while(robotClient.finished.value == False):
## val = input("enter something: ")
## if(len(val) > 0):
## robotClient.sendMessage(val)
##
##
##if(__name__ == "__main__"):
## try:
## robotServer = SocketComm(5555)
## print("waiting for client to connect...")
## robotServer.setupLine("")
## print("connected!")
## while(robotServer.finished.value == False):
## val = input("enter something: ")
## if(len(val) > 0):
## robotServer.sendMessage(val)
## except:
## pass
## finally:
## robotServer.closeConnection()
## sys.exit(0)

How to run a thread more than once in python

I am trying to run a thread more than once and keep getting an error:
RuntimeError: threads can only be started once
I have tried reading up multithreading and implementing it in my code without any luck.
Here is the function I am threading:
def receive(q):
host = ""
port = 13000
buf = 1024
addr = (host,port)
Sock = socket(AF_INET, SOCK_DGRAM)
Sock.bind(addr)
(data, addr) = Sock.recvfrom(buf)
q.put(data)
Here is the code I want to run:
q = Queue.Queue()
r = threading.Thread(target=receive, args=(q,))
while True:
r.start()
if q.get() == "stop":
print "Stopped"
break
print "Running program"
When the stop message gets sent, the program should break out of the while loop, but it does not run due to multithreading. The while loop should constantly print out Running program, until the stop message is sent.
The queue is used to receive the variable data from the receive function (which is the stop).
Here is a working example (for python 2.7).
The program has two modes of operation:
with no arguments it runs the receive loop
with arguments it sends a datagram
Note how r.start() and r.terminate() are called outside of the while loop in client.
Also, receive has a while True loop.
import sys
import socket
from multiprocessing import Process, Queue
UDP_ADDR = ("", 13000)
def send(m):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(m, UDP_ADDR)
def receive(q):
buf = 1024
Sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
Sock.bind(UDP_ADDR)
while True:
(data, addr) = Sock.recvfrom(buf)
q.put(data)
def client():
q = Queue()
r = Process(target = receive, args=(q,))
r.start()
print "client loop started"
while True:
m = q.get()
print "got:", m
if m == "stop":
break
print "loop ended"
r.terminate()
if __name__ == '__main__':
args = sys.argv
if len(args) > 1:
send(args[1])
else:
client()
I think the problem is once the thread is started, calling thread.start() again throws the error.
Using a try block would might work as a simple fix:
while True:
try:
r.start()
except Exception:
#or except RunTimeError:
pass
if q.get() == "stop":
print "Stopped"
break
print "Running program"

Tkinter gui with client server in Python

I have used a Tkinter to create a simple gui with client server running . However, I can get the client server communicating for what ever reason . Can someone look at my code an tell me why it is not working
Server :
import Tkinter as tk
import os
import socket # Required to allow network communicate
import re
w, h = 500, 200
connection = None
def key(self, event):
self.frame.focus_force()
connection.send(event.keysym) # Sends the command to the robot
def SendEnterCommand(event): # Bound to the Enter key
connection.send("enter") # Sends the command to the robot
print('Sent Message - Enter') # Feedback for the controller
def SendSpaceCommand(event): # Bound to the Space key
connection.send("space") # Sends the command to the robot
print('Sent Message - Space')# Feedback for the controller
def SendKillCommand(event): # Bound to the Escape key
connection.send("kill") # Sends the command to the robot
print('Sent Message - Kill')# Feedback for the controller
# Used to check if the IP address follows the correct format
def CheckIP(IP):
pat = re.compile("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$") # Check if the ip address value inputted follows the form of an ip address
test = pat.match(IP)
if test:
return True
else:
return False
def UpdateConnection(IPAddress, Port):
currentCommand = "empty"
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Initialise the socket
serversocket.bind((IPAddress, Port)) # Set up the socket on YOUR IP address and selected port
serversocket.listen(5) # Listen on the socket, up to 5 backlogged connections
print('waiting for a connection')
connection, client_address = serversocket.accept() # Wait for a connection, when there is one accept it
print ('Connected with ' + client_address[0] + ':' + str(client_address[1])) # Print who we are connected to
data = ""
while data != 'Kill': # Loop until the escape key is pressed
root.update()
def SetUpConnection():
IPAddress = IPEntry.get()
Port = int(PortEntry.get())
if CheckIP(IPAddress) and isinstance( Port, int ) and Port > 0 and Port < 9999: # check if the ip address is of the correct format, check if the port is an integer and greater than 0
#if InputMethodSelection.get() >= 1 and InputMethodSelection.get() <= 4: # check if there is a valid selected input option
print( "Connecting", "Connecting To Server!")
UpdateConnection(IPAddress, Port) # Connect and run the server
#else:
# print( "ERROR", "Select an input type!")
else:
tkMessageBox.showinfo( "ERROR", "Invalid IP address or port")
# Add a couple widgets. We're going to put pygame in `embed`.
root = tk.Tk()
embed = tk.Frame(root, width=w, height=h)
embed.pack()
BroadcastBTN = tk.Button(root, text='Broadcast', command=SetUpConnection)
BroadcastBTN.pack()
tk.Label(root, text="IP:").pack(anchor = "w")
IPEntry = tk.Entry(root)
IPEntry.config(width=20)
IPEntry.pack(anchor = "w")
tk.Label(root, text="Port:").pack(anchor = "w")
PortEntry = tk.Entry(root)
PortEntry.config(width=10)
PortEntry.pack(anchor = "w")
# Show the window so it's assigned an ID.
root.update()
root.bind("<Key>", key)
root.bind("<Return>", SendEnterCommand)
root.bind("<space>", SendSpaceCommand)
root.bind("<Escape>", SendKillCommand)
root.mainloop()
Client:
import socket # Required to allow network
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Initialise the socket
print('Connecting') # user guidance output
sock.connect(("192.168.1.59", 9559))
data = ""
print('I AM CONNECTED') # user guidance output
while data != 'Kill': # Loop until the computer tries to close the connection
data = sock.recv(1024) # Recieve data from the connection
if(data == "EnterPressed"):
print("Enter Pressed")
elif(data == "space"):
print("Space Pressed")
elif(data == "forward"):
print("Forward Pressed")
elif(data == "left"):
print("Left Pressed")
elif(data == "right"):
print("Right Pressed")
elif(data == "backward"):
print("Backward Pressed")
elif(data == "pressed"):
print("pressed Pressed")
else:
print(data)
sock.close()
print('DISCONNECTED') # user guidance output

Restarting socket connection following client disconnect

I have this code which listens/sends from/to a Scratch program with remote sensor connections enabled (e.g communicates by Port 42001 on 127.0.0.1)
# This code is copyright Simon Walters under GPL v2
# This code is derived from scratch_handler by Thomas Preston
# Version 5dev 11Aug08 Much better looping supplied by Stein #soilandreyes
# and someone else #MCrRaspJam who've name I've forgotton!
# Version 6dev - Moved Allon/AllOff to be processed before single pins :)
# Vesion 7dev - start to tidy up changes
# Vesion 8dev - use gpio-output system and broadcast allon, 1on system
# V0.1 - change to 6 out 2 in and sanitise the code
# V0.2 -
from array import *
import threading
import socket
import time
import sys
import struct
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11,GPIO.OUT)
GPIO.setup(12,GPIO.OUT)
GPIO.setup(13,GPIO.OUT)
GPIO.setup(15,GPIO.OUT)
GPIO.setup(16,GPIO.OUT)
GPIO.setup(18,GPIO.OUT)
GPIO.setup(22,GPIO.IN,pull_up_down=GPIO.PUD_UP)
GPIO.setup(7,GPIO.IN,pull_up_down=GPIO.PUD_UP)
'''
from Tkinter import Tk
from tkSimpleDialog import askstring
root = Tk()
root.withdraw()
'''
PORT = 42001
DEFAULT_HOST = '127.0.0.1'
#HOST = askstring('Scratch Connector', 'IP:')
BUFFER_SIZE = 240 #used to be 100
SOCKET_TIMEOUT = 1
SCRATCH_SENSOR_NAME_INPUT = (
'gpio-input0',
'gpio-input1'
)
SCRATCH_SENSOR_NAME_OUTPUT = (
'gpio-output0',
'gpio-output1',
'gpio-output2',
'gpio-output3',
'gpio-output4',
'gpio-output5'
)
SCRATCH_BROADCAST_NAME_OUTPUT = (
'1on','1off','2on','2off','3on','3off','4on','4off','5on','5off','6on','6off'
)
#Map gpio to real connector P1 Pins
GPIO_PINS = array('i',[11,12,13,15,16,18,22,7])
GPIO_PIN_OUTPUT = array('i')
GPIO_PIN_INPUT = array('i')
print "Output Pins are:"
for i in range(0,len(SCRATCH_SENSOR_NAME_OUTPUT)):
print GPIO_PINS[i]
GPIO_PIN_OUTPUT.append(GPIO_PINS[i])
print "Input Pins are:"
for i in range(len(SCRATCH_SENSOR_NAME_OUTPUT),8):
print GPIO_PINS[i]
GPIO_PIN_INPUT.append(GPIO_PINS[i])
class ScratchSender(threading.Thread):
#Not needed as its a Listening issue
...
class ScratchListener(threading.Thread):
def __init__(self, socket):
threading.Thread.__init__(self)
self.scratch_socket = socket
self._stop = threading.Event()
def stop(self):
self._stop.set()
def stopped(self):
return self._stop.isSet()
def physical_pin_update(self, pin_index, value):
physical_pin = GPIO_PIN_OUTPUT[pin_index]
print 'setting GPIO %d (physical pin %d) to %d' % (pin_index,physical_pin,value)
GPIO.output(physical_pin, value)
def run(self):
#This is main listening routine
while not self.stopped():
#time.sleep(0.1) # be kind to cpu
try:
data = self.scratch_socket.recv(BUFFER_SIZE)
dataraw = data[4:].lower()
print 'Length: %d, Data: %s' % (len(dataraw), dataraw)
if len(dataraw) == 0:
#This is probably due to client disconnecting
#I'd like the program to retry connecting to the client
time.sleep(2)
except socket.timeout:
print "sockect timeout"
time.sleep(1)
continue
except:
break
if 'sensor-update' in dataraw:
#gloablly set all ports
if 'gpio-outputall' in dataraw:
outputall_pos = dataraw.find('gpio-outputall')
sensor_value = dataraw[(outputall_pos+16):].split()
#print sensor_value[0]
for i in range(len(SCRATCH_SENSOR_NAME_OUTPUT)):
self.physical_pin_update(i,int(sensor_value[0]))
#check for individual port commands
for i in range(len(SCRATCH_SENSOR_NAME_OUTPUT)):
if 'gpio-output'+str(i) in dataraw:
#print 'Found '+ 'gpio-output'+str(i)
outputall_pos = dataraw.find('gpio-output'+str(i))
sensor_value = dataraw[(outputall_pos+14):].split()
#print sensor_value[0]
self.physical_pin_update(i,int(sensor_value[0]))
#Use bit pattern to control ports
if 'gpio-pattern' in dataraw:
#print 'Found gpio-outputall'
num_of_bits = len(SCRATCH_SENSOR_NAME_OUTPUT)
outputall_pos = dataraw.find('gpio-pattern')
sensor_value = dataraw[(outputall_pos+14):].split()
#print sensor_value[0]
bit_pattern = ('0000000000000000'+sensor_value[0])[-num_of_bits:]
#print 'bit_pattern %s' % bit_pattern
for i in range(len(SCRATCH_SENSOR_NAME_OUTPUT)):
#bit_state = ((2**i) & sensor_value) >> i
#print 'dummy gpio %d state %d' % (i, bit_state)
physical_pin = GPIO_PIN_OUTPUT[i]
if bit_pattern[-(i+1)] == '0':
print 'setting GPIO %d (physical pin %d) low' % (i,physical_pin)
GPIO.output(physical_pin, 0)
else:
print 'setting GPIO %d (physical pin %d) high' % (i,physical_pin)
GPIO.output(physical_pin, 1)
elif 'broadcast' in dataraw:
#print 'received broadcast: %s' % data
if 'allon' in dataraw:
for i in range(len(SCRATCH_SENSOR_NAME_OUTPUT)):
self.physical_pin_update(i,1)
if 'alloff' in dataraw:
for i in range(len(SCRATCH_SENSOR_NAME_OUTPUT)):
self.physical_pin_update(i,0)
for i in range(len(SCRATCH_SENSOR_NAME_OUTPUT)):
#check_broadcast = str(i) + 'on'
#print check_broadcast
if str(i+1)+'on' in dataraw:
self.physical_pin_update(i,1)
if str(i+1)+'off' in dataraw:
self.physical_pin_update(i,0)
if 'pin' + str(GPIO_PIN_OUTPUT[i])+'on' in dataraw:
GPIO.output(physical_pin, 1)
if 'pin' + str(GPIO_PIN_OUTPUT[i])+'off' in dataraw:
GPIO.output(physical_pin, 0)
elif 'stop handler' in dataraw:
cleanup_threads((listener, sender))
sys.exit()
else:
print 'received something: %s' % dataraw
def create_socket(host, port):
while True:
try:
print 'Trying'
scratch_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
scratch_sock.connect((host, port))
break
except socket.error:
print "There was an error connecting to Scratch!"
print "I couldn't find a Mesh session at host: %s, port: %s" % (host, port)
time.sleep(3)
#sys.exit(1)
return scratch_sock
def cleanup_threads(threads):
for thread in threads:
thread.stop()
for thread in threads:
thread.join()
if __name__ == '__main__':
if len(sys.argv) > 1:
host = sys.argv[1]
else:
host = DEFAULT_HOST
# open the socket
print 'Connecting...' ,
the_socket = create_socket(host, PORT)
print 'Connected!'
the_socket.settimeout(SOCKET_TIMEOUT)
listener = ScratchListener(the_socket)
sender = ScratchSender(the_socket)
listener.start()
sender.start()
# wait for ctrl+c
try:
while True:
time.sleep(0.5)
except KeyboardInterrupt:
cleanup_threads((listener, sender))
sys.exit()
The issue I'm having is in this section of code
def run(self):
#This is main listening routine
while not self.stopped():
#time.sleep(0.1) # be kind to cpu
try:
data = self.scratch_socket.recv(BUFFER_SIZE)
dataraw = data[4:].lower()
print 'Length: %d, Data: %s' % (len(dataraw), dataraw)
if len(dataraw) == 0:
#This is probably due to client disconnecting
#I'd like the program to retry connecting to the client
time.sleep(2)
except socket.timeout:
print "sockect timeout"
time.sleep(1)
continue
except:
break
If the client disconnects e.g Scratch is closed, I need this program to basically restart looking for a connection again and wait for Scratch to re-connect.
Could I have some suggestions as to how to achieve this please as I am a python newbie
regards
Simon
My solution was to use a global variable and change main loop structure
if len(dataraw) == 0:
#This is probably due to client disconnecting
#I'd like the program to retry connecting to the client
#tell outer loop that Scratch has disconnected
if cycle_trace == 'running':
cycle_trace = 'disconnected'
break
is used to break out of loop and
cycle_trace = 'start'
while True:
if (cycle_trace == 'disconnected'):
print "Scratch disconnected"
cleanup_threads((listener, sender))
time.sleep(1)
cycle_trace = 'start'
if (cycle_trace == 'start'):
# open the socket
print 'Starting to connect...' ,
the_socket = create_socket(host, PORT)
print 'Connected!'
the_socket.settimeout(SOCKET_TIMEOUT)
listener = ScratchListener(the_socket)
sender = ScratchSender(the_socket)
cycle_trace = 'running'
print "Running...."
listener.start()
sender.start()
# wait for ctrl+c
try:
#just pause
time.sleep(0.5)
except KeyboardInterrupt:
cleanup_threads((listener,sender))
sys.exit()
this is now my main outer loop
Seems to work :)

Categories