Tornado
Tornado is a non-blocking, extensible Web server and Python Web framework written using Python. You can use Tornado to write Web programs that do not rely on any Web server to directly provide efficient Web services. So tornado is not just a web framework but also an efficient Web server for production environments
Torando uses efficient asynchronous I/O models Epoll and kqueue for efficient Web servers on Linux and FreeBSD, so tornado can achieve the highest performance on Linux and the FreeBSD series
Interface
Of course, we can not only think of tornado as a web framework and Web server, we can use the interface provided by Tornado for efficient network asynchronous programming,
The Tornado.ioloop.IOLoop provides three interfaces that can be used for network programming:
Add_handlerdef Add_handler (self, FD, Handler, events): SELF._HANDLERS[FD] = stack_context.wrap (handler) self . _impl.register (FD, Events | self. ERROR)
Add_handler is used to add a socket to the main loop, accepting three parameters: FD is the file descriptor of the socket handler is the callback function that handles this socket * Events is the event that this socket is registered for
Update_handlerdef Update_handler (self, FD, events): self._impl.modify (FD, Events | self. ERROR)
The Update_handler is used to update a socket response event that already exists in the loop and accepts two parameters: FD is the file descriptor for the socket events is a new event registered
Remove_handlerdef Remove_handler (Self, FD): Self._handlers.pop (FD, none) Self._events.pop (FD, none) Try: self._impl.unregister (FD) except Exception: gen_log.debug ("Error deleting FD from Ioloop", Exc_info =true)
Remove_handler is used to remove a socket that already exists in the main loop
Event
The Tornado.ioloop.IOLoop also provides 4 response events:
Instance
Based on the interfaces and events above, we can write a simple echo server
#!/usr/bin/env python#-*-coding:utf-8-*-## author:cold# e-mail:wh_linux@126.com# date:13/04/15 15:08:51# Desc:tornado Echo server# home:http://www.linuxzen.com#import queueimport socketfrom functools Import Partialfrom Tornado.ioloop Import Ioloopsock = Socket.socket (socket.af_inet, socket. SOCK_STREAM) sock.setblocking (0) # Set socket to non-blocking server_address = ("localhost", 10000) Sock.bind (server_address) SOCK.L Isten (5) Fd_map = {} # file descriptor to socket mapping Message_queue_map = {} # socket to message queue mapping FD = Sock.fileno () fd_map[fd] = Sockiolo op = ioloop.instance () def handle_client (CLI_ADDR, FD, event): s = fd_map[fd] If event & IOLoop.READ:data = S.rec V (1024x768) if Data:print "received '%s ' from%s"% (data, CLI_ADDR) # received a message change event for write, used to send data to the peer IOLOOP.UPD Ate_handler (FD, Ioloop.write) message_queue_map[s].put (data) else:print "closing%s"% cli_addr Iolo Op.remove_handler (FD) s.close () del Message_queue_map[s] if EveNT & IOLoop.WRITE:try:next_msg = message_queue_map[s].get_nowait () except Queue.Empty:print "%s que UE Empty "% cli_addr Ioloop.update_handler (FD, Ioloop.read) else:print ' sending"%s "to%s '% (next_msg, CLI _ADDR) S.send (next_msg) if event & IOLoop.ERROR:print "exception on%s"% cli_addr Ioloop.remove_handler (FD) S.close () del message_queue_map[s]def handle_server (FD, event): s = fd_map[fd] If event & Ioloop.read: conn, cli_addr = s.accept () print "Connection%s"% cli_addr[0] conn.setblocking (0) conn_fd = Conn.fileno () FD_MAP[CONN_FD] = conn handle = partial (Handle_client, cli_addr[0]) # Add CLI_ADDR as the first parameter # joins and handle register as read events to torn ADO Ioloop Ioloop.add_handler (CONN_FD, handle, ioloop.read) message_queue_map[conn] = Queue.queue () # Create a corresponding message queue Iolo Op.add_handler (FD, Handle_server, Ioloop.read) Ioloop.start ()
The code above builds a non-blocking, efficient, asynchronous echo server