python 网络编程学习 epoll多路复用

来源:互联网 发布:淘宝运动鞋 编辑:程序博客网 时间:2024/06/06 01:36

捋一下阻塞非阻塞,同步异步概念

阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态

  • 阻塞:当前进程调用结果未返回,进程等待
  • 非阻塞:当前进程调用结果未返回,进程不等待

同步和异步关注的是消息通信机制

  • 异步:主动请求数据后便可以继续处理其他任务,等待IO操作完毕的通知(一般有调用特殊接口)
  • 同步:指主动请求并等待IO操作完毕,当数据就绪后等待读写完毕再返回

构建一个epoll多路复用的server所需的基本步骤

  1. 先构造一个套接字服务器,绑定到指定ip端口。
  2. 设置套接字为非阻塞模式 setblocking(0)。
  3. 设定TCP_NODELAY选项,可以让服务器无缓冲就可以直接交换数据。
  4. 创建一个select.epoll()实例,把套接字的文件描述符传递给epoll实例,以便监控
  5. run方法监听套接字事件,EPOLLIN(读事件), EPOLLOUT(写事件),EPOLLHUP(异常中断)

套接字的响应设置为SERVER_RES

import socket                                                                                                                                                                      import select                                                                                                                                                        EOL1 = b'\n\n'                                                                   EOL2 = b'\n\r\n'                                                                 SERVER_RES = b"""HTTP/1.1 200 OK\r\nDate: Mon, 1 Apr 2016 23:00:01               GMT\r\nContent-Type: text/plain\r\nContent-Length: 25\r\n\r\n                    Hello from epoll server!"""                                                                                                                                                                                                                        class EpollServer(object):                                                           def __init__(self, host='localhost', port=9999):                                     self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)                    self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)                  self.sock.bind((host, port))                                                     self.sock.listen(1)                                                              self.sock.setblocking(0)                                                         self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)                  print "Started epoll server(%s:%s)..." % (host, port)                            self.epoll = select.epoll()                                                      self.epoll.register(self.sock.fileno(), select.EPOLLIN)                                                                                                       def run(self):                                                                       try:                                                                                 connections = {}                                                                 requests = {}                                                                    responses = {}                                                                   while True:                                                                          events = self.epoll.poll(1)                                                      for fileno, event in events:                                                         print fileno, event, "......"                                                    if fileno == self.sock.fileno():                                                     connection, address = self.sock.accept()                                         connection.setblocking(0)                                                        self.epoll.register(connection.fileno(), select.EPOLLIN)                         connections[connection.fileno()] = connection                                    requests[connection.fileno()] = b''                                              responses[connection.fileno()] = SERVER_RES                                  elif event & select.EPOLLIN:                                                         requests[fileno] += connections[fileno].recv(1024)                               if EOL1 in requests[fileno] or EOL2 in requests[fileno]:                             self.epoll.modify(fileno, select.EPOLLOUT)                                       print "'-'*40 + '\n' + requests[fileno].decode()[:-2]"                    elif event & select.EPOLLOUT:                                                        byteswritten = connections[fileno].send(responses[fileno])                        responses[fileno] = responses[fileno][byteswritten:]                             if len(responses[fileno]) == 0:                                                      self.epoll.modify(fileno, 0)                                                     connections[fileno].shutdown(socket.SHUT_RDWR)                           elif event & select.EPOLLHUP:                                                        self.epoll.unregister(fileno)                                                    connections[fileno].close()                        del connections[fileno]                                          finally:                                                                             self.epoll.unregister(self.sock.fileno())                                        self.epoll.close()                                                               self.sock.close()                                                                                                                                                                                                                      if __name__ == '__main__':                                                           server = EpollServer('192.168.199.110', 6789)                                    server.run()

用浏览器访问这个web服务的时候, 正常返回服务端发送的

Hello from epoll server!

0 0
原创粉丝点击