在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]

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

在python中编写socket服务端模块(二):使用poll或epoll的更多相关文章

  1. python 并发编程 socket 服务端 客户端 阻塞io行为

    阻塞io行为 server.accept server.recv client.send recv,accept  分为两个阶段 1.wait for data 对方把数据经过网络延迟送到自己的操作系 ...

  2. 关于调试php的socket服务端中遇到的问题及解决办法

    今天终于把socket的服务端解决了,期间遇到了很多问题呢~ 1.用cmd运行php的问题: 2.socket_create()函数未定义问题: 3.查看端口的问题. 以下逐一说说解决办法: 1.在c ...

  3. 转:: 刺鸟:用python来开发webgame服务端(3)

    来源:http://ciniao.me/article.php?id=11 --------------- 刺鸟原创文章,转载请注明出处    在之前的准备工作中,我们已经建立了一个socket服务器 ...

  4. Python中的socket网络模块

    目录 Socket 服务端(server.py) 客户端(client.py) socket中的一些常用方法 Socket 对象(内建)方法 Python Internet 模块 Python3 提供 ...

  5. 转:: 刺鸟:用python来开发webgame服务端(1)

    来源:http://ciniao.me/article.php?id=9 --------------- 刺鸟原创文章,转载请注明出处    在开始之前,先简单描述一下项目的特点:我要实现的是一个mm ...

  6. Django---Http协议简述和原理,HTTP请求码,HTTP请求格式和响应格式(重点),Django的安装与使用,Django项目的创建和运行(cmd和pycharm两种模式),Django的基础文件配置,Web框架的本质,服务器程序和应用程序(wsgiref服务端模块,jinja2模板渲染模块)的使用

    Django---Http协议简述和原理,HTTP请求码,HTTP请求格式和响应格式(重点),Django的安装与使用,Django项目的创建和运行(cmd和pycharm两种模式),Django的基 ...

  7. socket服务端开发之测试使用threading和gevent框架

    socket服务端开发之测试使用threading和gevent框架 话题是测试下多线程和gevent在socket服务端的小包表现能力,测试的方法不太严谨,也没有用event loop + pool ...

  8. AutoCAD.net支持后台线程-Socket服务端

    最近因为公司项目的需求,CAD作为服务端在服务器中常驻运行,等待客户端远程发送执行任务的指令,最终确认用Socket-tcp通讯,CAD需要实时监听客户端发送的消息,这时就需要开启线程执行Socket ...

  9. 如何在Ruby中编写微服务?

    [编者按]本文作者为 Pierpaolo Frasa,文章通过详细的案例,介绍了在Ruby中编写微服务时所需注意的方方面面.系国内 ITOM 管理平台 OneAPM 编译呈现. 最近,大家都认为应当采 ...

随机推荐

  1. Linux学习之lsof命令

    lsof(list open files)是一个列出当前系统打开文件的工具.在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件.所以如传输控制协议 ...

  2. OC语法3——点语法,self关键字

    点语法:   为了给程序员提供便捷,OC中也引入了点语法.不过它和Java中点语法的意义是完全不同的. 在Java中无论调用任何方法,还是访问public类型的成员变量都是用点语法(.号). 而在OC ...

  3. 图片压缩上传 Android

    图片压缩的话 想保持 图像清晰度,但是又想保持图片的大小在100k左右. 同时的话又不想自己写那些压缩的代码的话.那你就找对地方了. 提供一个思路. 先读取你的文件,然后读到bitmap里面进行尺寸裁 ...

  4. Hive进阶(上)

    Hive进阶(上) Hive进阶(上) 执行数据导入 使用Load语句 语法: 1.LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE ...

  5. 对原生js的一些小尝试

    意图仿造JQ操作以及弄个个人工具箱,不断完善中,代码均为个人摸索,所以肯定会有不少不足的地方,希望读者们能提出来. var xzhUtils = { //-----DOM对象添加类----- //-- ...

  6. 64位windows8的 IIS运行32位COM组件报错的解决

    浏览时报错如下: Microsoft VBScript 运行时错误 错误 '800a01ad'ActiveX 部件不能创建对象: 'sqlcomp.FileSystemObject'/config.a ...

  7. Yaf-Plus 我们只谈框架这件事

    预热下,也算对自己的督促. Comming soon!

  8. [原创]C语言里为何会有“2+2=5”的结果

    原文链接:C语言里为何会有“2+2=5”的结果 写这篇原创文章是因为看到了极客中的一篇文章<有趣各种编程语言实现2+2=5>,其中C语言是这样实现的: int main() { ″; // ...

  9. J2SE知识点摘记(二十一)

    实现原理 前面已经提了一下Collection的实现基础都是基于数组的.下面我们就已ArrayList 为例,简单分析一下ArrayList 列表的实现方式.首先,先看下它的构造函数. 下列表格是在S ...

  10. java 操作配置文件 .properties

    package com.dms.common; import java.io.File; import java.io.FileInputStream; import java.io.FileNotF ...