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

http://blog.csdn.net/hongqun/article/details/19161841

#!/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]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值