在linux上编写socket服务端程序一般可以用select、poll、epoll三种方式,本文主要介绍使用poll和epoll编写socket服务端模块。

使用poll方式的服务器端程序代码:

import socket
import select
import Queue server_address=('10.0.2.15',21345)
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.setblocking(False)
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
server.bind(server_address)
server.listen(5) message_queues={}
#poll时间单位是毫秒
timeout = 1000 # Create a limit for the event
READ_ONLY = ( select.POLLIN | select.POLLPRI | select.POLLHUP | select.POLLERR)
READ_WRITE = (READ_ONLY|select.POLLOUT) # Set up the poller
poller = select.poll()
poller.register(server,READ_ONLY)
#Map file descriptors to socket objects
#server.fileno()是获得server这个socket的文件描述符,是int类型
fd_to_socket = {server.fileno():server,} while True: events = poller.poll(timeout)
#fd是描述符,flag是event状态,都是int类型
for fd ,flag in events:
# Retrieve the actual socket from its file descriptor
#s为当前的socket对象
s = fd_to_socket[fd] if flag & (select.POLLIN | select.POLLPRI) :
if s is server :
# A readable socket is ready to accept a connection
connection , client_address = s.accept()
print " Connection " , client_address
connection.setblocking(False) fd_to_socket[connection.fileno()] = connection
poller.register(connection,READ_ONLY) #Give the connection a queue to send data
message_queues[connection] = Queue.Queue()
else :
data = s.recv(1024)
if data:
# A readable client socket has data
print " received %s from %s " % (data, s.getpeername())
message_queues[s].put(data)
poller.modify(s,READ_WRITE)
else :
# Close the connection
print " closing" , s.getpeername()
# Stop listening for input on the connection
poller.unregister(s)
s.close()
del message_queues[s]
elif flag & select.POLLHUP :
#A client that "hang up" , to be closed.
print " Closing ", s.getpeername() ,"(HUP)"
poller.unregister(s)
s.close()
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 s.getpeername() , " queue empty"
poller.modify(s,READ_ONLY)
else :
print " sending %s to %s" % (next_msg , s.getpeername())
s.send(next_msg)
elif flag & select.POLLERR:
#Any events with POLLERR cause the server to close the socket
print " exception on" , s.getpeername()
poller.unregister(s)
s.close()
del message_queues[s]

使用epoll方式的服务器端程序代码跟poll方式类似,具体代码如下:

import socket
import select
import Queue server_address=('10.0.2.15',21345)
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.setblocking(False)
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
server.bind(server_address)
server.listen(5) message_queues={}
#poll时间单位是毫秒
timeout = 1000 # Create a limit for the event
READ_ONLY = ( select.EPOLLIN | select.EPOLLPRI | select.EPOLLHUP | select.EPOLLERR)
READ_WRITE = (READ_ONLY|select.EPOLLOUT) # Set up the poller
epoller = select.epoll()
epoller.register(server,READ_ONLY)
#Map file descriptors to socket objects
#server.fileno()是获得server这个socket的文件描述符,是int类型
fd_to_socket = {server.fileno():server,} while True:
print "Waiting for the next event"
events = epoller.poll(timeout)
print events
#fd是描述符,flag是event状态
for fd ,flag in events:
# Retrieve the actual socket from its file descriptor
s = fd_to_socket[fd] if flag & (select.EPOLLIN | select.EPOLLPRI) :
if s is server :
# A readable socket is ready to accept a connection
connection , client_address = s.accept()
print " Connection " , client_address
connection.setblocking(False) fd_to_socket[connection.fileno()] = connection
epoller.register(connection,READ_ONLY) #Give the connection a queue to send data
message_queues[connection] = Queue.Queue()
else :
data = s.recv(1024)
if data:
# A readable client socket has data
print " received %s from %s " % (data, s.getpeername())
message_queues[s].put(data)
epoller.modify(s,READ_WRITE)
else :
# Close the connection
print " closing" , s.getpeername()
# Stop listening for input on the connection
epoller.unregister(s)
s.close()
del message_queues[s]
elif flag & select.EPOLLHUP :
#A client that "hang up" , to be closed.
print " Closing ", s.getpeername() ,"(HUP)"
epoller.unregister(s)
s.close()
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 s.getpeername() , " queue empty"
epoller.modify(s,READ_ONLY)
else :
print " sending %s to %s" % (next_msg , s.getpeername())
s.send(next_msg)
elif flag & select.EPOLLERR:
#Any events with POLLERR cause the server to close the socket
print " exception on" , s.getpeername()
epoller.unregister(s)
s.close()
del message_queues[s]

客户端程序代码与上一篇博文中的相同。

最新文章

  1. [转]keil使用详解
  2. Entity Framework 使用Mysql的配置文件
  3. 如何用ZBrush做人体造型雕刻
  4. sql优化之(DMV)
  5. 为网站添加ico图标
  6. 淘宝初始化css代码
  7. .Net HttpPost的发送和接收示例代码
  8. openssl AES加密以及padding
  9. HDU 5785 Interesting
  10. CCNP交换实验(7) -- NAT
  11. Android 结合实例学会AsyncTask的使用方法
  12. Oracle数据库------体系结构
  13. JAVA基础第十组(5道题)
  14. Java-大集合拆分为指定大小的小集合
  15. iview 菜单数据的转换,动态加载
  16. Python和Python解释器
  17. MongoDB的ORM框架——Morphia
  18. nodejs 使用http模块保存源码
  19. SQL-常用命令
  20. 5月23日——SPA单页面应用的原理

热门文章

  1. zabbix监控服务器部署
  2. hadoop笔记之Hive的数据存储(视图)
  3. 使用javascript把图片转成base64位编码,然后传送到服务端(ajax调用的接口基于drupa7)
  4. 括号匹配算法 C语言实现
  5. Oracle EBS-SQL (SYS-24):职责列表
  6. 3.21 采购订单导入MDS
  7. Delphi判断一个文件是不是JPG图片
  8. opencv 图像修复函数
  9. html5的在ie6,7,8兼容
  10. [Java 8 Lambda] java.util.stream 简单介绍