您的位置:首页 > 运维架构 > Linux

服务器的实现(采用poll方式,只能在linux下运行

2014-08-21 12:16 309 查看
/article/9031083.html

#!/usr/bin/env python

# encoding: utf-8

import select

import socket

import sys

import Queue

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server.setblocking(0)

server_address = ('localhost', 10000)

print >>sys.stderr, 'starting up on %s port %s' % server_address

server.bind(server_address)

server.listen(5)

message_queues = {}

TIMEOUT = 1000

"""

poll的底层实现比select高效,但是poll在windows下不被支持

"""

# poll监听5种事件

# POLLIN:输入准备好

# POLLPRI:带外数据可读

# POLLOUT:准备好接受数据

# POLLERR:有错误发生

# POLLHUP:通道关闭

# POLLVAL:通道未打开

#只读事件组合

READ_ONLY = ( select.POLLIN |

select.POLLPRI |

select.POLLHUP |

select.POLLERR )

#读写事件组合

READ_WRITE = READ_ONLY | select.POLLOUT

#得到poll对象

poller = select.poll()

#在poll对象中注册server套接字,并让poller监听该套接字的READ_ONLY事件

poller.register(server, READ_ONLY)

#由于poller.poll返回的是元素为(fd,flag)的列表,所以我们必须保存fd与相应socket对象的映射

fd_to_socket = { server.fileno(): server,

}

while True:

#监听已注册的socket事件,返回元素为(描述符,事件标志)的列表

print >>sys.stderr, 'waiting for the next event'

events = poller.poll(TIMEOUT)

for fd, flag in events:

s = fd_to_socket[fd]

#处理输入事件

if flag & (select.POLLIN | select.POLLPRI):

#当有新连接到来

if s is server:

connection, client_address = s.accept()

print >>sys.stderr, ' connection', client_address

connection.setblocking(0)

fd_to_socket[ connection.fileno() ] = connection

#将与客户端通讯的socket对象注册到poll对象中,并让poll监听该对象的只读属性

poller.register(connection, READ_ONLY)

message_queues[connection] = Queue.Queue()

#客户端有数据到来

else:

data = s.recv(1024)

if data:

print >>sys.stderr, ' received "%s" from %s' % \

(data, s.getpeername())

message_queues[s].put(data)

# 让poll对象监听该套接字对象的读写属性

poller.modify(s, READ_WRITE)

#客户端断开

else:

print >>sys.stderr, ' closing', client_address

poller.unregister(s)

s.close()

del message_queues[s]

#套接字可写

elif flag & select.POLLOUT:

# Socket is ready to send data, if there is any to send.

try:

next_msg = message_queues[s].get_nowait()

except Queue.Empty:

# No messages waiting so stop checking

print >>sys.stderr, s.getpeername(), 'queue empty'

#如果没数据可写,则不监听写事件

poller.modify(s, READ_ONLY)

else:

print >>sys.stderr, ' sending "%s" to %s' % \

(next_msg, s.getpeername())

s.send(next_msg)

#通道关闭

elif flag & select.POLLHUP:

# Client hung up

print >>sys.stderr, ' closing', client_address, '(HUP)'

poller.unregister(s)

s.close()

del message_queues[s]

#发生错误

elif flag & select.POLLERR:

print >>sys.stderr, ' exception on', s.getpeername()

poller.unregister(s)

s.close()

del message_queues[s]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐