服务器的实现(采用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]
#!/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]
相关文章推荐
- NAT方式实现远程服务器中Linux虚拟机访问外网
- Linux非阻塞IO(五)使用poll实现非阻塞的回射服务器客户端
- Windows 采用Socket方式实现服务器和客户端的数据访问
- Linux下的单进程多用户TCP服务器,采用select方法实现。
- 实现tomcat做服务器在windows/linux下开机自动运行
- Linux Socket 多并发服务器开源代码:xSocketd 实现PPC/TPC/SELECT/POLL/EPOLL
- Linux下两种TCP网络服务器实现方式:循环服务&并发服务
- CentOS中安装subversion,并使用svn+ssh访问 ;Linux下采用RSA key的方式登录服务器
- Linux下实现MySQL多端口多实例运行(第一种方式)
- 通过crond自动运行Python脚本实现多台linux服务器的监控
- Linux crontab的使用方式,sh脚本的编写,sh脚本自动启动tomcat服务器,sh监控系统运行情况
- Linux下实现MySQL多端口多实例运行(第二种方式)
- select和poll服务器实现(Linux)
- Linux中poll实现高性能服务器及优缺点总结
- Linux非阻塞IO(五)使用poll实现非阻塞的回射服务器客户端
- 从.NET迁移到.NET Core的一个主要原因,在于后者具备在Linux上运行的能力。但是对于大型企业应用,不可能实现一步迁移到位。由此,Microsoft推荐采用一种逐步迁移做法: 第一步,迁移到
- linux 服务器,通过脚本方式,运行java类
- Linux下两种TCP网络服务器实现方式:循环服务&并发服务
- linux下在root用户登陆状态下,以指定用户运行脚本程序实现方式
- Linux下采用RSA key的方式登录服务器