This question already has an answer here:
thread starts running before calling Thread.start
(1 answer)
Closed 2 years ago.
I am trying to run a thread within a thread. When I execute monitor.startMonitoring(), it gets stuck in that function, specifically on threading.Thread(target=self._startMonitoring(), daemon=True).start().
What can I do so I can go to the last line (print function call) of the code?
host = '127.0.0.1'
port = 9000
def _receiveHealthMsg(clientsock, clientaddr):
try:
while True:
print(f'{clientaddr} : {clientsock.recv(1024).decode("utf-8")}: '
f'{datetime.datetime.now().isoformat()}')
except ConnectionResetError:
print("Connection has been severed")
class Monitor:
def __init__(self, host, port):
self._sock = socket.socket()
self._sock.bind((host, port))
self._sock.listen(5)
self._threads = []
self._clients = []
def startMonitoring(self):
threading.Thread(target=self._startMonitoring(), daemon=True).start()
def _startMonitoring(self):
while True:
c, addr = self._sock.accept()
thread = threading.Thread(target=_receiveHealthMsg, args=(c, addr))
thread.start()
self._threads.append(thread)
self._clients.append((c, addr))
monitor = Monitor(host, port)
monitor.startMonitoring()
print('do some stuff here while threads are running')
You called _start_monitoring, you didn't pass it as a function to run. Change the line to:
threading.Thread(target=self._startMonitoring, daemon=True).start()
# ^ parentheses removed
Related
I'm trying to write a very simple Port Scanner in Python, and it was working great until I decided to introduce threading, in order to speed things up.
I want to include a brief summary at the end, which lists the ports that are open. I've put this in a function called finish. However, since introducing threading, that summary appears as the first line in the output of my code, no matter where I put it.
Is there a way I can effectively confine threading to the functions I need it for, and then turn it off before it gets to the summary/finish(), or am I just making an obvious mistake? Any help would be much appreciated.
Code:
from socket import *
from threading import *
screenLock = Semaphore(value=1)
open_ports = []
def scan(ip,port):
try:
s = socket(AF_INET, SOCK_STREAM)
s.connect((ip, port))
screenLock.acquire()
print ('Scanning ', ip , 'on port', port)
print("Port",port, "is open")
s.close()
summary(port)
except:
screenLock.acquire()
print ('Scanning ', ip , 'on port', port)
print("Port",port,"is closed")
finally:
screenLock.release()
s.close()
def loop():
for i in range(1,100):
ip = '192.168.0.38'
port = int(i)
t = Thread(target=scan, args=(ip,int(port)))
t.start()
return
def summary(port):
global open_ports
open_ports.append(port)
return
def main():
loop()
finish()
def finish():
print('The following ports are open:',open_ports)
main()
You have to wait for all the Threads to finish:
def loop():
threads = []
for i in range(1,100):
ip = '192.168.0.38'
port = int(i)
t = Thread(target=scan, args=(ip,int(port)))
t.start()
threads.append(t)
[t.join() for t in threads]
I'm trying to run several sockets on different ports as the following:
Socket:
import socket
class Receiver:
TCP_IP = '127.0.0.1' # by default
TCP_PORT = 1999 # by default
BUFFER_SIZE = 1024
def __init__(self, TCP_IP, TCP_PORT):
self.TCP_IP = TCP_IP
self.TCP_PORT = TCP_PORT
def initialize(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((self.TCP_IP, self.TCP_PORT))
s.listen(1)
conn, addr = s.accept()
print('Connection address:', addr)
while 1:
data = conn.recv(self.BUFFER_SIZE)
if not data: break
rdata = 'U'.encode() + data
print("received data:", data[1:5])
conn.send(rdata[0:5]) # echo
conn.close()
And Runner:
from NVGEmulator.Receiver import Receiver
import threading
class FireStarter:
def starter(self):
nvgEmu1 = Receiver('127.0.0.1', 2999)
print("FIRST INITIALIZED")
nvgEmu1.initialize()
nvgEmu2 = Receiver('127.0.0.1', 2998)
nvgEmu2.initialize()
print("SECOND INITIALIZED")
def starter_second(self):
nvgEmu2 = Receiver('127.0.0.1', 2998)
print("SECOND INITIALIZED")
nvgEmu2.initialize()
if __name__ == '__main__':
print("Receiver has been started")
fs = FireStarter()
thr = threading.Thread(target=fs.starter())
thr.start()
thr.join()
thr2 = threading.Thread(target=fs.starter_second())
thr2.start()
When I run FireStarter, it runs only the first instance of socket. I've read that there is "threading" library which can run several processes in async, but anyway there is no result, cause in console I see that "FIRST INITIALIZED". How to run the second or the third socket listener? May be there is another approach to do this.
You have two problems in that code.
The first one: here the second socket is waiting for the first one to end as it is trapped in the while loop:
def starter(self):
nvgEmu1 = Receiver('127.0.0.1', 2999)
print("FIRST INITIALIZED")
nvgEmu1.initialize()
nvgEmu2 = Receiver('127.0.0.1', 2998)
nvgEmu2.initialize()
print("SECOND INITIALIZED")
The second one is this join sentence thr.join(), with that you are forcing the second thread to wait for the first one, avoiding to run it in parallel.
Probably the approach I would follow is spawning a thread within the initialize function inside your Receiver class and manage the thread there (maybe extending the Thread class), with that you avoid to spawn by yourself a new thread each time and you have your code more encapsulated.
I have a multithreaded program in python and I would like to close the socket after CTRL+C (or Z). I've tried this and this but none of them had worked.
When trying to re-run the program, error message appears:
Bind failed. Error code: 98 Message Address already in use called
Traceback (most recent call last): File "main.py", line 16, in
main.connection.close() NameError: name 'main' is not defined
from connection import Connection
class Main():
def __init__(self):
self.connection = Connection()
self.connection.start()
if __name__ == '__main__':
try:
main = Main()
except:
main.connection.close()
import socket
import sys
import threading
import time
class Connection(threading.Thread):
def __init__(self, group=None, target=None, name=None, args=(), kwargs=None, verbose=None):
threading.Thread.__init__(self, group=group, target=target, name=name, args=args, kwargs=kwargs, verbose=verbose)
self.server = None
self.connection = self.start_connention()
self.data = "null"
self.lock = threading.Lock()
self.OK = True
def start_connention(self):
host = '192.168.42.1'
port = 8888
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
print 'Socket created'
#Bind socket to local host and port
try:
s.bind((host, port))
except socket.error, 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 on ' + str(port)
connection, addr = s.accept()
print 'Connected with ' + addr[0] + ':' + str(addr[1])
self.server = s
return connection
def close(self):
print("closing")
self.OK = False
self.server.close()
def run(self):
while self.OK:
with self.lock:
self.data = self.connection.recv(4096)
print(str(self.data))
time.sleep(0.02)
def send(self, message):
self.connection.sendall(message)
From docs: The KeyboardInterrupt inherits from BaseException so as to not be accidentally caught by code that catches Exception and thus prevent the interpreter from exiting. docs
if __name__ == '__main__':
try:
main = Main()
except KeyboardInterrupt:
pass
finally:
main.connection.close()
I would suggest you to use atexit module to this stuff.
Just put this line in __init__ and in case any python process termination a connection will be close
atexit.register(self.close)
I tried to create multithreaded echo server:
echomain.py:
#!/usr/bin/python
from echoserver import echoserver
server = echoserver()
print server.isRunning()
print server.port()
server.start()
print "Main program continues..."\\This part is not displayed(((
echoserver.py:
#!/usr/bin/python
import threading
import socket
class connection(threading.Thread):
def __init__(self, sock, addr):
self.sock = sock
self.addr = addr
threading.Thread.__init__(self)
def run (self):
while True:
buffer = self.sock.recv(1024)
if buffer == "disconnect\r\n":
self.sock.send("bye")
break
elif buffer:
self.sock.send(buffer)
self.sock.close()
class echoserver(object):
def __init__(self, port=12119):
self.running = False
self._port = port
self._socket = None
def isRunning(self):
return self.running
def port(self):
return self._port
def start(self):
self.running = True
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self._socket.bind(("0.0.0.0", self.port()))
self._socket.listen(5)
while True:
conn, addr = self._socket.accept()
connection(conn, addr).start()
def stop(self):
self._socket.close()
print "Server is closed..."
Could somebody help me in how I can launch echoserver class as a thread so it run simultaneously with main program so I could stop it with stop() method in echomain.py part?
Change your runner program to run the server as a thread:
echomain.py:
#!/usr/bin/python
from echoserver import echoserver
from threading import Thread
import time
server = echoserver()
print server.isRunning()
print server.port()
# server.start()
# run server in a different thread
serverThread = Thread(target=server.start)
serverThread.start()
print "main - server started"
# wait ten seconds before stopping
time.sleep(10)
server.stop()
print "main - server stopped"
print "Main program continues..."
This example simply stops the server after 10 seconds.
The simplest way is to have your echoserver itself be a Thread as proposed by Reut Sharabani, but IMHO, you should also implement a correct stop() method, ensuring that all children have ended.
Here is my implementation of your script :
#!/usr/bin/python
import threading
import socket
class connection(threading.Thread):
def __init__(self, sock, addr, parent):
self.sock = sock
self.addr = addr
self.parent = parent
threading.Thread.__init__(self)
self.sock.settimeout(None)
self.closed = False # will be set to True on thread end
def run (self):
while not self.parent._stopped:
buffer = self.sock.recv(1024)
if buffer == "disconnected\r\n":
self.sock.send("bye")
break
elif buffer:
self.sock.send(buffer)
self.sock.close()
self.closed = True
class echoserver(threading.Thread):
def __init__(self, port=12119):
threading.Thread.__init__(self)
self.running = False
self._port = port
self._socket = None
self._stopped = False
self._conns = [] # list of active connections
def isRunning(self):
return self.running
def port(self):
return self._port
def run(self):
self.running = True
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self._socket.bind(("0.0.0.0", self.port()))
self._socket.listen(5)
self._socket.settimeout(5) # use a timeout to respond to stop()
while not self._stopped:
try:
conn, addr = self._socket.accept()
c = connection(conn, addr, self)
self._conns.append(c) # add child the the list
c.start()
except Exception as e:
# print e # in debug
pass
self._conns = self.child_list() # remove closed child from list
self._socket.close()
print "Server is closing..."
for connect in self._conns: # join active children
connect.join()
print "Server is closed"
def stop(self):
self._stopped = True
def child_list(self):
l = []
for conn in self._conns:
if conn.closed:
conn.join()
else:
l.append(conn)
return l
Remarks :
you simply use it that way :
serv=echoserver()
serv.start()
... # sleep of do anything you want
serv.stop()
if no connection is active when you call stop() all stops at the end of the accept timeout and you get :
Server is closing...
Server is closed
if at least one connection is active when you call stop(), you get only Server is closing... at the end of the accept timeout. Then for each connection, it will end as soon as it receives a packet, and will be joined by echoserver. Then when all connection are over, you will get Server is closed and echoserver thread will terminate
that means that in you main thread you have only to do
serv.stop()
serv.join()
to be sure that all other threads are correctly terminated, and that all sockets are closed
In Python 3.3.3, i create a thread to listen some connection to the socket.It likes this:
import threading
import socket
import time
Host = ''
Port = 50000
flag = False
class ServerThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def run(self):
try:
self._sock.bind((Host, Port))
self._sock.listen(5)
while True:
conn, addr = self._sock.accept()
print('Connected by', addr)
except socket.error as msg:
print(msg)
except Exception as e:
print(str(e))
finally:
self._sock.close()
def exit(self):
self._sock.close()
def TargetFunc(vlock):
vlock.acquire()
flag = True
vlock.release()
def main():
sthread = ServerThread()
sthread.start()
vlock = threading.Lock()
time.sleep(10)
vthread = threading.Thread(target = TargetFunc, args = (vlock, ))
vthread.start()
while True:
vlock.acquire()
if flag:
sthread.exit()
vlock.release()
break
vlock.release()
sthread.join()
vthread.join()
if __name__ == '__main__':
main()
There are two threads, one is listening socket, the other is to set a flag. When the flag is True, close the socket, then raise a socket error and catch it, so the listening socket terminates.But why it does not work this.
Thanks!
self._sock.accept() is blocking. So it will wait until somebody connects. You should use a nonblocking variant (or blocking but with a time-out). So that you can check the exit conditions.
Alternatively you could force an exception in the ServerThread.