python 异步I/O

本文介绍了Python中使用select和epoll实现异步I/O的方法。通过监听socket,接受新连接,接收并发送数据,展示了一个简单的异步服务器的工作流程。select在套接字数量大时效率较低,而epoll采用事件通知模式,性能更优。
摘要由CSDN通过智能技术生成
#!usr/bin/env python
#coding:utf-8

import select
import socket
import Queue

server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.setblocking(False)
server_address=('127.0.0.1', 8000)
server.bind(server_address)
server.listen(5)

read=[server]
write=[]
error=[]
message_queues={}
timeout=20

#select(read[],write[],error[],timeout)轮询监控3个list
#所以当list比较大的时候,非常耗时

while (Ture):
	readlist, writelist, errorlist=select.select(read, write, error, timeout)
	for s in readlist:
		#当服务器socket可用时,接入客户端,并将客户端加入可读处进行监听
		if s is server:
			conn, address=s.accept()
			con.setblocking(0)
			readlist.append(con)
			message_queues[con]=Queue.Queue()
		#如果客户端发来消息,则将客户端加入读队列,读取客户端消息
		else:
			data=s.recv(1024)
			if data:
				#将数据加入队列中
				message_queues[s].put(data)
			#标记客户端为write,准备向客户端写消息
				if s not in writelist:
					writelist.append(s)
			#客户端没有发来消息,关闭连接
			else:
				if s in writelist:
					writelist.remove(s)
				readlist.remove(s)
				s.close()
				del message_queues[s]
	for s in writelist:
		#发送消息

	for s in errorlist:
		#处理异常

#epoll基于回调事件通知模式
#!/usr/bin/python
# -*- coding: utf-8 -*-
import socket, select
import Queue
 
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_address = ("192.168.1.5", 8080)
serversocket.bind(server_address)
serversocket.listen(1)
print  "服务器启动成功,监听IP:" , server_address
serversocket.setblocking(0)
timeout = 10
#新建epoll事件对象,后续要监控的事件添加到其中
epoll = select.epoll()
#添加服务器监听fd到等待读事件集合
epoll.register(serversocket.fileno(), select.EPOLLIN)
message_queues = {}
 
fd_to_socket = {serversocket.fileno():serversocket,}
while True:
  print "等待活动连接......"
  #轮询注册的事件集合
  events = epoll.poll(timeout)
  if not events:
     print "epoll超时无活动连接,重新轮询......"
     continue
  print "有" , len(events), "个新事件,开始处理......"
  for fd, event in events:
     socket = fd_to_socket[fd]
     #可读事件
     if event & select.EPOLLIN:
         #如果活动socket为服务器所监听,有新连接
         if socket == serversocket:
            connection, address = serversocket.accept()
            print "新连接:" , address
            connection.setblocking(0)
            #注册新连接fd到待读事件集合
            epoll.register(connection.fileno(), select.EPOLLIN)
            fd_to_socket[connection.fileno()] = connection
            message_queues[connection]  = Queue.Queue()
         #否则为客户端发送的数据
         else:
            data = socket.recv(1024)
            if data:
               print "收到数据:" , data , "客户端:" , socket.getpeername()
               message_queues[socket].put(data)
               #修改读取到消息的连接到等待写事件集合
               epoll.modify(fd, select.EPOLLOUT)
     #可写事件
     elif event & select.EPOLLOUT:
        try:
           msg = message_queues[socket].get_nowait()
        except Queue.Empty:
           print socket.getpeername() , " queue empty"
           epoll.modify(fd, select.EPOLLIN)
        else :
           print "发送数据:" , data , "客户端:" , socket.getpeername()
           socket.send(msg)
     #关闭事件
     elif event & select.EPOLLHUP:
        epoll.unregister(fd)
        fd_to_socket[fd].close()
        del fd_to_socket[fd]
epoll.unregister(serversocket.fileno())
epoll.close()
serversocket.close()












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值