How to make the run server methos thread safe? - python

I am using the "run" method in python that is running the web server.
I want to make it thread safe by using mutex.
How can i do this and where should i locate the mutex?
Thanks.
def run(serverClass=FlsLdkServiceThreadedHttpServer, handlerClass=FlsLdkServiceRequestHandler, hostName="localhost", port=1111):
serverAddress = (hostName, int(port))
httpd = serverClass(serverAddress, handlerClass)
logging.info("start")
if sConfigIsSecure == "Yes":
httpd.socket = ssl.wrap_socket(httpd.socket, certfile=sConfigCert, keyfile=sConfigPrivKey, server_side=True)
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()
logging.info('Stop')

Related

How to stop server socket using ctrl+c in Python

When i run my server, when server is listening, there is no way to stop the server rather than closing the terminal. I tried to handle ctrl+c using KeyboardInterrupt, but it doesnt work. I can terminate the script using ctrl+break but i dont know how to handle it in my code.
Here is the code for my server:
import socket
try:
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listener.bind(('127.0.0.1', 4444))
listener.listen(0)
print('Listening...')
listener.accept()
print('Got a connection.')
except KeyboardInterrupt:
print('Exiting...')
exit()
How can i handle ctrl+break in my code?
If no client is waiting, socket.accept() hangs until a connection is made and can't be interrupted by CTRL-C or CTRL-BREAK. Use select.select() to wait for a connection to be readable from the server socket along with a timeout. The timeout will allow CTRL-C and CTRL-BREAK to be recognized.
CTRL-C raises KeyboardInterrupt, but CTRL-BREAK needs a signal handler. I've set up a custom exception to be raised on the SIGBREAK signal below:
import signal
import socket
import select
# Custom exception with same base class as KeyboardInterrupt
class CtrlBreakInterrupt(BaseException):
pass
def handler(*args):
raise CtrlBreakInterrupt
signal.signal(signal.SIGBREAK, handler)
# Set up server
with socket.socket() as sock:
sock.bind(('', 5000))
sock.listen()
# Loop, accepting one connection at a time.
while True:
try:
# Check server has a connection with timeout
readable, _, _ = select.select([sock], [], [], 1.0)
if sock in readable:
with sock.accept() as (client, address):
while True:
data = client.recv(4096)
if not data: break
print(data)
except CtrlBreakInterrupt:
print('CTRL-BREAK')
break
except KeyboardInterrupt:
print('CTRL-C')
break
something like this .
def handler(signum, frame):
print 'Shutting down...'
sys.exit(1)
signal.signal(signal.SIGTERM, handler)
while True:
clientsocket, address = listener.accept()
clientsocket.send(bytes("hi.","utf-8"))

Cannot connect to multi-threaded TCP server

I'm trying to setup a threaded server where multiple clients can connect at the same time. This is a bit long, please do bear with me. I've already read this helpful realpython article on sockets as well as the socket and socketserver docs.
Python provides facilities to create a server and the socketserver documentation even shows us:
import socket
import threading
import socketserver
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
data = str(self.request.recv(1024), 'ascii')
cur_thread = threading.current_thread()
response = bytes("{}: {}".format(cur_thread.name, data), 'ascii')
self.request.sendall(response)
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
def client(ip, port, message):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((ip, port))
sock.sendall(bytes(message, 'ascii'))
response = str(sock.recv(1024), 'ascii')
print("Received: {}".format(response))
if __name__ == "__main__":
# Port 0 means to select an arbitrary unused port
HOST, PORT = "localhost", 0
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
with server:
ip, port = server.server_address
# Start a thread with the server -- that thread will then start one
# more thread for each request
server_thread = threading.Thread(target=server.serve_forever)
# Exit the server thread when the main thread terminates
server_thread.daemon = True
server_thread.start()
print("Server loop running in thread:", server_thread.name)
client(ip, port, "Hello World 1")
client(ip, port, "Hello World 2")
client(ip, port, "Hello World 3")
server.shutdown()
This works fine on my machine but what I'd like to de-couple the client implementation from the server. So I split the implementations and I have.
server.py:
import socketserver
import threading
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
data = str(self.request.recv(1024), 'ascii')
cur_thread = threading.current_thread()
response = bytes("{}: {}".format(cur_thread.name, data), 'ascii')
self.request.sendall(response)
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
def main():
HOST, PORT = "localhost", 8080 # localhost aka 127.0.0.1
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
with server:
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = False # Do not stop and keep serving
server_thread.start()
print("Server loop running in thread: ", server_thread.name)
if __name__ == '__main__':
main()
and client.py
import socket
class Client:
def __init__(self, ip, port):
self.ip = ip
self.port = port
def start(self, message):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((self.ip, self.port))
sock.sendall(bytes(message, "ascii"))
response = str(sock.recv(1024), "ascii")
print("Received: {}".format(response))
def main():
client = Client("localhost", 8080)
client.start("Hello World!")
if __name__ == '__main__':
main()
Then I open two different shell occurences and I do:
$ python3 -m server
The server outputs its message and the shell hangs, which is the expected behavior since I turned daemon mode off and it is supposed to serve forever.
Pinging localhost works fine, all packages are received with no loss. On the other hand, using netstat, I can't seem to find the port I'm opening (8080).
and in the other:
$ python3 -m client
Fails with a ConnectionRefusedError which is the typical error when there is nothing to connect to.
My conclusion for now is that the server is closing the port at some point, I suppose when the main thread dies?
I'm not sure how to fix it though? What's wrong with the current implementation.
Thanks for the help.

How to restart a TCP socketserver?

I have written a code for handling multiple requests at a time but my server freezes randomly after a while, is there any way to check and restart the server if there is no activity.
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
#doing some work and generating response
self.request.sendall(response)
if __name__ == "__main__":
HOST, PORT = "0.0.0.0", 4879
socketserver.TCPServer.allow_reuse_address = True
with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
try:
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
server.socket.close()
via bash if you want to stop the server ps aux|grep The name of the program|awk '{print $2}'|xargs kill

Build a server with BaseHTTPServer for public network?

Trying to build a simple server:
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
class MyHandler(BaseHTTPRequestHandler):
def do_GET(self):
try:
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write("It works!")
return
except IOError:
self.send_error(404,'File Not Found: %s' % self.path)
try:
server = HTTPServer(('localhost', 8080), MyHandler)
print 'started httpserver...'
server.serve_forever()
except KeyboardInterrupt:
print '^C received, shutting down server'
server.socket.close()
Well, it works on 127.0.0.1:8080, but now I want to access it through public network like my ip:8080, what should I do?
Edit: HTTPServer(('0.0.0.0', 8080), MyHandler) does not work for me, any idea why?
I'm on win 7 ultimate 64bit, python 2.7.3
Specify '0.0.0.0' or '' (empty string) to make the server accept connections from anywhere.
server = HTTPServer(('0.0.0.0', 8080), MyHandler)
The address ('0.0.0.0', 8080) is passed to socket.bind. 0.0.0.0 is used to bind to any local network interfaces.

KeyboardInterrupt Threads

I'm writing a simple TCP socket server with pyBonjour support. To do this I figured using threading. The problem is how I get the server to stop... I figured the following should work (according to this) but it isn't
Is there a nicer way to do this (that works)..
import SocketServer
import threading
import pybonjour
import select
import time
class BonjourThread(threading.Thread):
def run(self):
sdRef = pybonjour.DNSServiceRegister(name = 'MacroServer - Mac',
regtype = '_macroserver._tcp',
port = 12000,
callBack = self.bonjour_register_callback)
while True:
ready = select.select([sdRef], [], [])
if sdRef in ready[0]:
pybonjour.DNSServiceProcessResult(sdRef)
def bonjour_register_callback(self, sdRef, flags, errorCode, name, regtype, domain):
if errorCode == pybonjour.kDNSServiceErr_NoError:
print 'Bonjour started'
class TCPThread(threading.Thread):
def run(self):
try:
HOST, PORT = "localhost", 12000
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
print 'TCP server started'
server.serve_forever()
except KeyboardInterrupt:
print 'Closing Down'
exit()
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
try:
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print "{} wrote:".format(self.client_address[0])
print self.data
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
except KeyboardInterrupt:
print 'Closing Down'
exit()
if __name__ == "__main__":
try:
thread1 = TCPThread()
thread1.start()
thread2 = BonjourThread()
thread2.start()
while True: time.sleep(100)
except (KeyboardInterrupt, SystemExit):
print 'Received keyboard interrupt, quitting threads.\n'
finally:
print 'And its bye from me'
In python, only the main thread gets the KeyboardInterrupt signal. How you want to handle termination of your socket servers and their various clients can get complex. I've made logging servers where I kept the sockets in a master list, protected by a lock, and closed them all then waited for termination in the keyboard interrupt. You could even mark the threads as daemons and just exit - let the operating system clean up the sockets.
from place you linked to:
thread.daemon=True causes the thread to terminate when the main process ends.
which you missed in your code, so that's why they don't stop
as to nicer ways to do it, you could create your own signal handler and terminate your threads but not sure if it's any nicer than:
thread.daemon=True

Categories