Threading wxPython and XMLRPC - python

I am doing an app whit wxPython and XMLRPC i need that the window does an action every time the XMLRPC server has a request
How could i do it without blocking the main Window?
I tried with threads but it doesnt work also I tried calling the run method of the thread in the Frame's constructor neither it worked
Sorry for the language
I hope to be clear
Thanks

Here's an example of a threaded XMLRPC server using SimpleXMLRPCServer. Note the wx.CallAfter to call into the wx main thread and the "return 0" (though you can configure the server so that return values of None are OK.)
from SimpleXMLRPCServer import SimpleXMLRPCServer
import threading
class XMLRPCServerThread(threading.Thread):
def __init__(self, remoteObject, host='localhost', port=8000):
self.remoteObject = remoteObject
self.host = host
self.port = port
threading.Thread.__init__(self)
def stop(self):
self.server.shutdown()
def run(self):
self.server = SimpleXMLRPCServer( (self.host, self.port), logRequests=False )
self.server.register_instance( self.remoteObject )
self.server.serve_forever()
class MyRemoteCalls(object):
def __init__(self, obj):
self.obj = obj
def exampleCall(self, arg):
wx.CallAfter(self.obj.method, arg)
return 0
def getRPCThread(obj, host='localhost', port=8000):
remoteObj = MyRemoteCalls(obj)
rpcThread = XMLRPCServerThread(remoteObj, host, port)
rpcThread.start()
return rpcThread

Related

How to communicate from the Request Handler to a Socket Server

I have the following two Python classes:
import socketserver
class MyServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
def __init__(self, server_address):
socketserver.TCPServer.__init__(self, server_address, MyTcpHandler)
self.allow_reuse_address = True
self.serve_forever()
class MyTcpHandler(socketserver.BaseRequestHandler):
data = ""
def handle(self):
self.data = self.request.recv(BUFF_SIZE).strip()
if self.data == b"shutdown":
self.request.close()
import threading
threading.Thread(target=SERVER.shutdown).start()
Thus, when the client sends "shutdown", the server itself should shutdown. As a workaround I set the global variable SERVER to the MyServer object, then I call SERVER.shutdown in another thread, as shown above.
But using a global variable is ugly as hell. So how can I communicate directly from the request handler with the socket server instead?
The server is available as self.server according to the Python docs here https://docs.python.org/2/library/socketserver.html#SocketServer.BaseRequestHandler.handle

Passing a Queue to ThreadedHTTPServer

I would like to pass a Queue object to a base ThreadedHTTPServer implementation. My existing code works just fine, but I would like a safe way to send calls to and from my HTTP requests. Normally this would probably be handled by a web framework, but this is a HW limited environment.
My main confusion comes on how to pass the Queue (or any) object to allow access to other modules in my environment.
The base code template I have currently running:
import base64,threading,urlparse,urllib2,os,re,cgi,sys,time
import Queue
class DemoHttpHandler(BaseHTTPRequestHandler):
def __init__(self, request, client_address, server,qu):
BaseHTTPRequestHandler.__init__(self, request, client_address, server)
def do_GET(self):
...
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
"""Handle requests in a separate thread."""
def main():
listen_interface = "localhost"
listen_port = 2323
server = startLocalServer.ThreadedHTTPServer((listen_interface, listen_port), startLocalServer.DemoHttpHandler)
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
print 'started httpserver thread...'
Your code does not run but I modified it so that it will run:
import base64,threading,urlparse,urllib2,os,re,cgi,sys,time
import Queue
class DemoHttpHandler(BaseHTTPRequestHandler):
def __init__(self, request, client_address, server):
BaseHTTPRequestHandler.__init__(self, request, client_address, server)
self.qu = server.qu # save the queue here.
def do_GET(self):
...
self.qu # access the queue self.server.qu
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
"""Handle requests in a separate thread."""
def main():
listen_interface = "localhost"
listen_port = 2323
qu = Queue.Queue()
server = startLocalServer.ThreadedHTTPServer((listen_interface, listen_port), startLocalServer.DemoHttpHandler)
server.qu = qu # store the queue in the server
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
print 'started httpserver thread...'

Very simple python client/server working, but strange delays

I am trying to learn how to use sockets and a useful asynchronous backend. I've started in python with asyncore. After reading various online posts I've written a very simple chat server and connection client, reproduced below.
It seems to work. I open a python interactive session and type
> import chatserver
> server = chatserver.EchoServer('localhost', 7667)
> server.serve()
Then I open another IPython interactive session and type
> import chatserver
> cxn = chatserver.Connection()
> cxn._connect('localhost', 7667)
When I do that, I get a log output in the server window indicating that a connection has been made. Good. Then I type
> cxn.say('hi')
Nothing happens for a while, and then log messages show up for the server and client as expected.
Why is this delay ocurring?
Am I using the log functionality correctly?
I used threading to make it so that I could use the interactive session while the asyncore loop does it's thing for the Connection. Did I do this in a reasonable way?
(optional) If I don't include the line self.out_buffer="" in the Connection._connect function I get an error saying that .out_buffer does not exist. What's up with this?
import asyncore
import socket
import logging
import threading
logging.basicConfig(level=logging.DEBUG, format="%(created)-15s %(msecs)d %(levelname)8s %(thread)d %(name)s %(message)s")
log = logging.getLogger(__name__)
class Connection(asyncore.dispatcher_with_send):
def __init__(self):
asyncore.dispatcher.__init__(self)
def _connect(self, host, port, timeout=5, password=None):
self.host = host
self.port = port
self.out_buffer=""
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect((host, port))
#Run the asyncore loop in its own thread so that we can use the interactive session
self.loop = threading.Thread(target=asyncore.loop)
self.loop.daemon = True
self.loop.start()
def say(self, msg):
self.out_buffer = msg
def handle_read(self):
data = self.recv(4096)
log.debug('Received %s'%data)
class EchoHandler(asyncore.dispatcher_with_send):
def handle_read(self):
log.debug("handle_read")
data = self.recv(1024)
log.debug("after recv")
if data:
log.debug("got data: %s"%data)
self.out_buffer = data
else:
log.debug("got null data")
class EchoServer(asyncore.dispatcher):
SOCKET_TYPE = socket.SOCK_STREAM
ADDRESS_FAMILY = socket.AF_INET
def __init__(self, host, port):
self.address = (host,port)
asyncore.dispatcher.__init__(self)
self.create_socket(self.ADDRESS_FAMILY, self.SOCKET_TYPE)
log.debug("bind address=%s %s"%(host,port))
self.bind(self.address)
self.listen(1)
def fileno(self):
return self.socket.fileno()
def serve(self):
asyncore.loop()
#Start asyncore loop in new thread
# self.loop = threading.Thread(target=asyncore.loop)
# self.loop.daemon = True
# self.loop.start()
def handle_accept(self):
"""Deal with a newly accepted client"""
(connSock, clientAddress) = self.accept()
log.info("conn made: clientAddress=%s %s"%(clientAddress[0], clientAddress[1]))
#Make a handler for this connection
EchoHandler(connSock)
def handle_close(self):
self.close()
Looking at the asyncore docs you are relying on asyncore.dispatcher_with_send to call send() and the default timeout for asyncore.loop() is 30 seconds. This may explain the delay.
It turns out the problem was as Eero suggested.
I made two changes:
In EchoServer
asyncore.loop() to asyncore.loop(timeout=0.1)
In Connection
self.loop = threading.Thread(target=asyncore.loop) to self.loop = threading.Thread(target=asyncore.loop, kwargs={'timeout':0.1})
The response is now much faster. This seems like a hack though so if someone can explain a way to get the same effect in a proper way please contribute.

Start a TCPServer with ThreadingMixIn again in code directly after shutting it down. (Gives `Address already in use`)

I try to program a TCPServer with threads (ThreadingMixIn) in Python. The problem is that I can't shut it down properly as I get the socket.error: [Errno 48] Address already in use when I try to run it again. This is a minimal example of the python code that triggers the problem:
import socket
import threading
import SocketServer
class FakeNetio230aHandler(SocketServer.BaseRequestHandler):
def send(self,message):
self.request.send(message+N_LINE_ENDING)
def handle(self):
self.request.send("Hello\n")
class FakeNetio230a(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
def __init__(self, server_address, RequestHandlerClass):
self.allow_reuse_address = True
SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass)
if __name__ == '__main__':
for i in range(2):
fake_server = FakeNetio230a(("", 1234), FakeNetio230aHandler)
server_thread = threading.Thread(target=fake_server.serve_forever)
server_thread.setDaemon(True)
server_thread.start()
# might add some client connection here
fake_server.shutdown()
All the main code should do is to start the server, shut it down and run it again. But it triggers the error stated above because the socket has not been released after the first shutdown.
I thought that setting self.allow_reuse_address = True could solve the problem, but that did not work. When the python program finishes I can run it again straight away and it can start the server once (but again not twice).
However the problem is gone when I randomize the port (replace 1234 by 1234+i for example) as no other server is listening on that address.
There is a similar SO Q Shutting down gracefully from ThreadingTCPServer but the solution (set allow_reuse_address to True does not work for my code and I don't use ThreadingTCPServer).
How do I have to modify my code in order to be able to start the server twice in my code?
Some more information: The reason why I'm doing this is that I want to run some unit tests for my python project. This requires to provide a (fake) server that my software should to connect to.
edit:
I just found the most correct answer to my problem: I have to add fake_server.server_close() at the end of my main execution code (right after fake_server.shutdown()). I found it in the source file of the TCPServer implementation. All it does is self.socket.close().
Somehow, fake_server doesn't unbind when you assign to it (in first line in for statement).
To fix that, just remove fake_server at the end of loop:
del fake_server # force server to unbind
This post helped me get over the un-closed socket problem.
I had the same problem and wanted to post here my simple implementation for TCP server class (and client method).
I made a TCPThreadedServer class. In order to use it is needed to be inherited, and the method process(msg) must be overridden. the overridden method invokes every time the server gets a message msg, and if it returns a not None object, it will be returned as string to the connected client.
from SocketServer import TCPServer, StreamRequestHandler, ThreadingMixIn
import threading
class TCPThreadedServer(TCPServer, ThreadingMixIn):
class RequstHandler(StreamRequestHandler):
def handle(self):
msg = self.rfile.readline().strip()
reply = self.server.process(msg)
if reply is not None:
self.wfile.write(str(reply) + '\n')
def __init__(self, host, port, name=None):
self.allow_reuse_address = True
TCPServer.__init__(self, (host, port), self.RequstHandler)
if name is None: name = "%s:%s" % (host, port)
self.name = name
self.poll_interval = 0.5
def process(self, msg):
"""
should be overridden
process a message
msg - string containing a received message
return - if returns a not None object, it will be sent back
to the client.
"""
raise NotImplemented
def serve_forever(self, poll_interval=0.5):
self.poll_interval = poll_interval
self.trd = threading.Thread(target=TCPServer.serve_forever,
args = [self, self.poll_interval],
name = "PyServer-" + self.name)
self.trd.start()
def shutdown(self):
TCPServer.shutdown(self)
TCPServer.server_close(self)
self.trd.join()
del self.trd
I found it quite easy to use:
class EchoServerExample(TCPThreadedServer):
def __init__(self):
TCPThreadedServer.__init__(self, "localhost", 1234, "Server")
def process(self, data):
print "EchoServer Got: " + data
return str.upper(data)
for i in range(10):
echo = EchoServerExample()
echo.serve_forever()
response = client("localhost", 1234, "hi-%i" % i)
print "Client received: " + response
echo.shutdown()
I used the method:
import socket
def client(ip, port, msg, recv_len=4096,
timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
msg = str(msg)
response = None
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((ip, port))
if timeout != socket._GLOBAL_DEFAULT_TIMEOUT:
sock.settimeout(timeout)
sock.send(msg + "\n")
if recv_len > 0:
response = sock.recv(recv_len)
finally:
sock.close()
return response
Enjoy it!
Change your FakeNetio230a definition to this:
class FakeNetio230a(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
def __init__(self, server_address, RequestHandlerClass):
self.allow_reuse_address = True
SocketServer.TCPServer.__init__(self,
server_address,
RequestHandlerClass,
False) # do not implicitly bind
Then, add these two lines in your entry point below your FakeNetio230a instantiation:
fake_server.server_bind() # explicitly bind
fake_server.server_activate() # activate the server
Here's an example:
if __name__ == '__main__':
for i in range(2):
fake_server = FakeNetio230a(("", 1234), FakeNetio230aHandler)
fake_server.server_bind() # explicitly bind
fake_server.server_activate() # activate the server
server_thread = threading.Thread(target=fake_server.serve_forever)
server_thread.setDaemon(True)
server_thread.start()
# might add some client connection here
fake_server.shutdown()

Python DNS Server

I am adding a feature to my current project that will allow network admins to install the software to the network. I need to code a DNS server in Python that will allow me to redirect to a certain page if the request address is in my list. I was able to write the server, just not sure how to redirect.
Thank you. I am using Python 2.6 on Windows XP.
There's little, simple example here that can easily be adapted to make all kinds of "mini fake dns servers". Note that absolutely no "redirect" is involved (that's not how DNS works): rather, the request is for a domain name, and the result of that request is an IP address. If what you want to do is drastically different from translating names to addresses, then maybe what you need is not actually a DNS server...?
Using circuits and dnslib here's a full recursive dns server written in Python in only 143 lines of code:
#!/usr/bin/env python
from __future__ import print_function
from uuid import uuid4 as uuid
from dnslib import CLASS, QR, QTYPE
from dnslib import DNSHeader, DNSQuestion, DNSRecord
from circuits.net.events import write
from circuits import Component, Debugger, Event
from circuits.net.sockets import UDPClient, UDPServer
class lookup(Event):
"""lookup Event"""
class query(Event):
"""query Event"""
class response(Event):
"""response Event"""
class DNS(Component):
def read(self, peer, data):
record = DNSRecord.parse(data)
if record.header.qr == QR["QUERY"]:
return self.fire(query(peer, record))
return self.fire(response(peer, record))
class ReturnResponse(Component):
def response(self, peer, response):
return response
class Client(Component):
channel = "client"
def init(self, server, port, channel=channel):
self.server = server
self.port = int(port)
self.transport = UDPClient(0, channel=self.channel).register(self)
self.protocol = DNS(channel=self.channel).register(self)
self.handler = ReturnResponse(channel=self.channel).register(self)
class Resolver(Component):
def init(self, server, port):
self.server = server
self.port = port
def lookup(self, qname, qclass="IN", qtype="A"):
channel = uuid()
client = Client(
self.server,
self.port,
channel=channel
).register(self)
yield self.wait("ready", channel)
self.fire(
write(
(self.server, self.port),
DNSRecord(
q=DNSQuestion(
qname,
qclass=CLASS[qclass],
qtype=QTYPE[qtype]
)
).pack()
)
)
yield (yield self.wait("response", channel))
client.unregister()
yield self.wait("unregistered", channel)
del client
class ProcessQuery(Component):
def query(self, peer, query):
qname = query.q.qname
qtype = QTYPE[query.q.qtype]
qclass = CLASS[query.q.qclass]
response = yield self.call(lookup(qname, qclass=qclass, qtype=qtype))
record = DNSRecord(
DNSHeader(id=query.header.id, qr=1, aa=1, ra=1),
q=query.q,
)
for rr in response.value.rr:
record.add_answer(rr)
yield record.pack()
class Server(Component):
def init(self, bind=("0.0.0.0", 53)):
self.bind = bind
self.transport = UDPServer(self.bind).register(self)
self.protocol = DNS().register(self)
self.handler = ProcessQuery().register(self)
class App(Component):
def init(self, bind=("0.0.0.0", 53), server="8.8.8.8", port=53,
verbose=False):
if verbose:
Debugger().register(self)
self.resolver = Resolver(server, port).register(self)
self.server = Server(bind).register(self)
def main():
App().run()
if __name__ == "__main__":
main()
Usage:
By default this example binds go 0.0.0.0:53 so you will need to do something like:
sudo ./dnsserver.py
Otherwise change the bind parameter.
Here is a dns serer/proxy that works for me written in python:
http://thesprawl.org/projects/dnschef/
I wrote a DNS Server using Python Twisted library for NameOcean.net. You can see examples on https://twistedmatrix.com/documents/16.5.0/names/howto/custom-server.html.

Categories