import SocketServer
import sys
from Queue import *
import threading
class CustomTCPServer(SocketServer.TCPServer):
def __init__(self, server_address, RequestHandlerClass, commandQueue=Queue):
self.queue = commandQueue
SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate=False)
SocketServer.TCPServer.allow_reuse_address = True
self.server_bind()
self.server_activate()
class SingleTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
commandQueue = self.server.queue
self.data = self.request.recv(1024).strip()
try:
commandQueue.put(self.data)
except Queue.Empty:
print 'Sorry.. Cannot accept any more.. Queue is full..'
def main():
HOST = ''
PORT = 50099
commandQueue = Queue()
server = CustomTCPServer((HOST, PORT), SingleTCPHandler, commandQueue)
threadObject = threading.Thread(target=server.serve_forever)
threadObject.setDaemon(True)
threadObject.start()
threadObject.join()
if __name__ == '__main__':
main()
But whenever I run the code for second time I get the message that
socket.error: [Errno 98] Address already in use
I am confused..
Any suggestion would be appreciated..
Instead of:
SocketServer.TCPServer.allow_reuse_address = True
Which sets the value on the base class that you've already subclassed yourself from, (and created an instance of),
Use:
self.allow_reuse_address = True
It doesn't look like you're ever closing the socket at the end. Try adding a server.shutdown() (as well as changing the allow_reuse_address) to shut it down at the end after the thread join.
Related
I made the follow class:
class Client(socket.socket):
def __init__(self):
super(Client, self).__init__()
self.settimeout(None)
self.radd = None
self.port = None
self.buffersize = None
def connect_to_server(self):
self.connect((self.radd, self.port))
def configure(self, radd:str, port=49305, buffersize=2048):
# close the socket
self.close()
# assign a new configuration
self.radd = radd
self.port = port
self.buffersize = buffersize
and i used it as follow:
c = Client()
c.configure('192.168.1.1')
c.connect_to_server()
but i get the error: [WinError 10038]
Can anyone tell me why this happens?
Error 10038 is WSAENOTSOCK.
An operation was attempted on something that is not a socket.
It is happening because you are closing the socket before you connect. If you call close(), you have to create a new socket after that.
How do I send without calling Reactor.ListenUDP?
If I try, then I get an exception in the protocol class that the transport is NULL. It seems it doesn't get set up in the base class until you call the reactor.ListenUDP. Surely, you have the ability to send without listening for incoming messages. After all, a server might not even want to receive at all.
----main.py------
import wx
from twisted.internet import wxreactor
from main_window import MainWindow
def main():
app = wx.App(False)
frame = MainWindow(None, 'UDP Demo')
from twisted.internet import reactor
reactor.registerWxApp(app)
reactor.run()
if __name__ == "__main__":
wxreactor.install()
main()
---main_window.py---
# SNIP - Nothing really relevant. Just creates the classes below and hooks up buttons to call their methods
---plugin.py----
from enum import Enum
from twisted.internet.error import CannotListenError
from udp_protocol import UDPProtocol
class PluginBase(object):
"""
This is just a dummy class to match what is in Falco
"""
def __init__(self, app_dist, *args, **kwargs):
pass
class Plugin(PluginBase):
class State(Enum):
"""
Represents the states that the plugin can be in
"""
CLOSED = 0 # Initial state
LISTENING = 1 # After open() is called
RECV_CALLBACK_REGISTERED = 2 # After listen() is called
def __init__(self, app_dist, *args, **kwargs):
super(Plugin, self).__init__(app_dist, *args, **kwargs)
self.state = self.State.CLOSED
self.port = None
self.listener = None
self.listen_callback = None
self.protocol = UDPProtocol(self.on_data_received)
def listen(self, port, isBroadcast, callback, errback=None):
if self.state != self.State.CLOSED:
raise RuntimeError("UDP Plugin already in an opened state")
self.port = port
# Start listening
try:
from twisted.internet import reactor
self.listener = reactor.listenUDP(self.port, self.protocol)
self.state = self.State.LISTENING
callback()
except CannotListenError as err:
error_json = {"error": err[2].strerror}
if errback is not None:
errback(error_json)
def stop_listening(self):
if self.listener is not None:
self.listener.stopListening()
self.listener = None
self.listen_callback = None
self.port = None
self.state = self.State.CLOSED
def send(self, addr, port, data):
# While it seems like one could send without listening for incoming messages,
# twisted's implementation doesn't seem to work that way?
# The transport in the protocol object only gets created when we call reactor.listenUDP,
# as far as I can tell
if self.state == self.State.CLOSED:
raise RuntimeError(
"UDP Plugin must be in an open state before attempting to send")
self.protocol.send(addr, port, data)
# SNIP recv
----udp_protocol.py---
from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
class MyProtocol(DatagramProtocol):
def datagramReceived(self, data, (host, port)):
print "received %r from %s:%d" % (data, host, port)
self.transport.write(data, (host, port))
def send(self, addr, port, data):
self.transport.write(data, (addr, port))
Surely, you have the ability to send without listening for incoming messages.
As it turns out, no. However, nothing compels you to do anything with any incoming messages that arrive.
I am new to python and wrote a simple httpserver in python. I am trying to shut down the server from the request to the server. How can I achieve this functionality of calling a function of the server from the handler?
class MyHandler(SimpleHTTPRequestHandler):
def do_GET(self):
if self.path == '/shutdown':
pass # I want to call MainServer.shutdown from here
class MainServer()
def __init__(self, port = 8123):
self._server = HTTPServer(('0.0.0.0', port), MyHandler)
self._thread = threading.Thread(target = self._server.serve_forever)
self._thread.deamon = True
def start(self):
self._thread.start()
def shut_down(self):
self._thread.close()
In short, do not use server.serve_forver(..). The request handler has a self.server attribute that you can use to communicate with the main server instance to set some sort of flag that tell the server when to stop.
import threading
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
class MyHandler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/shutdown':
self.server.running = False
class MainServer:
def __init__(self, port = 8123):
self._server = HTTPServer(('0.0.0.0', port), MyHandler)
self._thread = threading.Thread(target=self.run)
self._thread.deamon = True
def run(self):
self._server.running = True
while self._server.running:
self._server.handle_request()
def start(self):
self._thread.start()
def shut_down(self):
self._thread.close()
m = MainServer()
m.start()
The server is normally accessible from the handler through the server attribute. A HTTPServer that was started with server_forerver can be shut down with its... shutdown() method. Unfortunately, even if it is not documented, you cannot call shutdown from the thread that runs the server loop because it causes a deadlock. So you could write this in your do_GET handler method:
def do_GET(self):
# send something to requester...
if self.path == '/shutdown':
t = threading.Thread(target = self.server.shutdown)
t.daemon = True
t.start()
This will cleanly let the thread to terminate, and you should also use it as you server shut_down method, because Python threads cannot be closed abruptly:
def shut_down(self):
self._server.shutdown()
I have a script which sets up a BasicHTTPServer in a thread so that the main script can automatically open a web browser pointing to the server url to download a file. After the file is downloaded, I want to shut down that server but I have no clue how to go about it. This is an example of what I've done currently:
def server():
HandlerClass = SimpleHTTPRequestHandler
ServerClass = BaseHTTPServer.HTTPServer
Protocol = 'HTTP/1.0'
server_address = ('127.0.0.1', 8000)
HandlerClass.protocol_version = Protocol
httpd = ServerClass(server_address, HandlerClass)
httpd.serve_forever()
def download():
t = threading.Thread(name='server', target=server)
t.start()
webbrowser.open('safari-http://127.0.0.1:8000/')
I want to shut down the server after webbrowser.open().
Thank you
I tried the example given here. Can you check if it worked for you.
runFlag = True
def server(server_class=BaseHTTPServer.HTTPServer,
handler_class=BaseHTTPServer.BaseHTTPRequestHandler):
global runFlag
server_address = ('127.0.0.1', 8000)
HandlerClass.protocol_version = Protocol
httpd = ServerClass(server_address, HandlerClass)
while runFlag:
httpd.handle_request()
httpd.shutdown()
def download():
t = threading.Thread(name='server', target=server)
t.start()
webbrowser.open('https:\\www.google.com')
global runFlag
runFlag = False
So after digging deep through many articles I managed to find a kind of messy solution that works for me which closes the server completely. To do it I incorporated code from the following sources:
The Green Place
Corey Goldberg
UI is a module exclusive to the iOS Python IDE Pythonista which basically just creates buttons "start", "stop" and "visit" which bind to their respective _t functions. The ui.in_background decorator just lets the ui remain responsive while things happen in the background.
self.httpd.socket.close() is what really closes the server but it's messy and prints an ugly error to stdout/err so I had no choice but to suppress it by redirecting stdout/err to a dead class so the error is dropped. Standard stdout/err behaviour is restored immediately after. Thank you all for the time and effort you took to help me, I appreciate it greatly.
import console
import BaseHTTPServer
import SocketServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
import sys
import threading
import webbrowser
from time import sleep
import ui
original_stdout = sys.stdout
original_stderr = sys.stderr
class BasicServer(SocketServer.TCPServer):
allow_reuse_address = True
class NullifyOutput():
def write(self, s):
pass
class ServerThread(threading.Thread):
def __init__(self, ip, port):
super(ServerThread, self).__init__()
self.ip = ip
self.port = port
self.HandlerClass = SimpleHTTPRequestHandler
self.Protocol = 'HTTP/1.0'
self.server_address = (self.ip, self.port)
self.HandlerClass.protocol_version = self.Protocol
try:
self.httpd = BasicServer(self.server_address, self.HandlerClass)
except:
self.port += 1
self.server_address = (self.ip, self.port)
self.httpd = BasicServer(self.server_address, self.HandlerClass)
self.stoptheserver = threading.Event()
def run(self):
while not self.stoptheserver.isSet():
self.httpd.handle_request()
def join(self, timeout=None):
self.stoptheserver.set()
self.httpd.socket.close()
super(ServerThread, self).join(timeout)
server = ServerThread('127.0.0.1', 8000)
def start_t(sender):
print server.isAlive()
if not server.isAlive():
server.start()
def visit_t(sender):
webbrowser.open('http://127.0.0.1:' + str(server.port))
#webbrowser.open('safari-http://127.0.0.1' + str(server.port))
# Use the safari- prefix to open in safari. You may need to switch to
# pythonista then back to safari to get the page to load.
#ui.in_background
def stop_t(sender):
sys.stdout, sys.stderr = NullifyOutput(), NullifyOutput()
server.join(3)
sys.stdout, sys.stderr = original_stdout, original_stderr
ui.load_view('SimpleServer').present('sheet')
Here is an example from cryptoassets.core project, status server:
class StatusHTTPServer(threading.Thread):
def __init__(self, ip, port):
threading.Thread.__init__(self)
self.running = False
self.ready = False
self.ip = ip
self.port = port
def run(self):
self.running = True
self.ready = True
self.httpd.serve_forever()
self.running = False
def start(self):
server_address = (self.ip, self.port)
try:
self.httpd = HTTPServer(server_address, StatusGetHandler)
except OSError as e:
raise RuntimeError("Could not start cryptoassets helper service status server at {}:{}".format(self.ip, self.port)) from e
threading.Thread.start(self)
def stop(self):
if self.httpd and self.running:
self.httpd.shutdown()
self.httpd = None
I'm trying to figure out why I can't kill my multi threaded SocketServer via a CRTL-C.
Basically I have that :
import SocketServer,threading
class TEST(SocketServer.BaseRequestHandler):
def server_bind(self):
self.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR,SO_REUSEPORT, 1)
self.socket.bind(self.server_address)
self.socket.setblocking(0)
def handle(self):
request, socket = self.request
data = request
if data[0] == "\x01":
buff = "blablabla"
socket.sendto(str(buff), self.client_address)
class TEST1(SocketServer.BaseRequestHandler):
def server_bind(self):
self.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR,SO_REUSEPORT, 1)
self.socket.bind(self.server_address)
self.socket.setblocking(0)
def handle(self):
request, socket = self.request
data = request
if data[0] == "\x01":
buff = "blablabla"
socket.sendto(str(buff), self.client_address)
class TEST2(SocketServer.BaseRequestHandler):
def server_bind(self):
self.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR,SO_REUSEPORT, 1)
self.socket.bind(self.server_address)
self.socket.setblocking(0)
def handle(self):
request, socket = self.request
data = request
if data[0] == "\x01":
buff = "blablabla"
socket.sendto(str(buff), self.client_address)
class TEST3(SocketServer.BaseRequestHandler):
def server_bind(self):
self.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR,SO_REUSEPORT, 1)
self.socket.bind(self.server_address)
self.socket.setblocking(0)
def handle(self):
request, socket = self.request
data = request
if data[0] == "\x01":
buff = "blablabla"
socket.sendto(str(buff), self.client_address)
def serve_thread_udp(host, port, handler):
server = SocketServer.UDPServer((host, port), handler)
server.serve_forever()
def serve_thread_tcp(host, port, handler):
server = SocketServer.TCPServer((host, port), handler)
server.serve_forever()
def main():
try:
threading.Thread(target=serve_thread_tcp,args=('', 4045,TEST)).start()
threading.Thread(target=serve_thread_tcp,args=('', 239,TEST1)).start()
threading.Thread(target=serve_thread_udp,args=('', 1246,TEST2)).start()
threading.Thread(target=serve_thread_tcp,args=('', 12342,TEST3)).start()
except KeyboardInterrupt:
os._exit()
if __name__ == '__main__':
try:
main()
except:
raise
I'm trying to understand what i've done wrong and what would be the best way to be able to kill the whole script via a crtl-c.
Any help would be greatly appreciated !
Thanks
Here is a solution:
def main():
import thread
try:
thread.start_new(serve_thread_tcp, ('', 4045,TEST))
thread.start_new(serve_thread_tcp,('', 239,TEST1))
thread.start_new(serve_thread_udp,('', 1246,TEST2))
thread.start_new(serve_thread_tcp,('', 12342,TEST3))
except KeyboardInterrupt:
os._exit()
if __name__ == '__main__':
try:
main()
except:
raise
raw_input()
To close the server you can type return or close the stdin.
The Problem is with the Thread class that will not allow closing the application before all Threads are closed.
serve_forever() will not end until you close the belonging to server(an other solution) on KeyboardInterrupt.
When creating threads, set them as daemon :
Thread.__init__(self)
self.setDaemon(True)
In this way all the thread will terminate when you have killed the main thread.
Based on python documentation in here :
A thread can be flagged as a “daemon thread”. The significance of this flag is that the entire Python program exits when only daemon threads are left. The initial value is inherited from the creating thread. The flag can be set through the daemon property.