热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python高并发selectsocket_python实现select和epoll模型socket网络编程

这里简单搞搞select和eopll的接口开发~select目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,事实上从现在看来,

这里简单搞搞 select 和 eopll 的接口开发 ~

select 目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,事实上从现在看来,这也是它所剩不多的优点之一,现在其实更多的人用 epoll,在 python 下 epoll 文档有点少,就先讲究搞搞 select ~

select 的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在 Linux 上一般为 1024,不过可以通过修改宏定义甚至重新编译内核的方式提升这一限制。

说点我的理解,要是用烦了多线程的网络编程,可以试试 select 的模型。

传递给 select 的参数是几个列表,分别表示读事件、写事件和错误事件。select 方法返回三个列表,其中包含满足条件的对象(读、写和异常)。

服务端的代码:

#coding:utf-8

import socket,select

import time

import os

#xiaorui.cc

host = "localhost"

port = 50000

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

s.bind((host,port))

s.listen(5)

while 1:

infds,outfds,errfds = select.select([s,],[],[],5)

if len(infds) != 0:

clientsock,clientaddr = s.accept()

buf = clientsock.recv(8196)

if len(buf) != 0:

print (buf)

os.popen('sleep 10').read()

clientsock.close()

# print "no data coming"

客户端的代码:

#coding:utf-8

import socket,select

#xiaorui.cc

host = "localhost"

port = 50000

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

s.connect((host,port))

s.send("coming from select client")

s.close()

一个完成的 select 的例子:

这里有队列的概念

#

import select

import socket

import Queue

import time

import os

#创建 socket 套接字

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

server.setblocking(False)

#配置参数

server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR , 1)

server_address= ('192.168.0.101',9999)

server.bind(server_address)

server.listen(10)

inputs = [server]

outputs = []

message_queues = {}

#timeout = 20

while inputs:

print "waiting for next event"

# readable , writable , exceptional = select.select(inputs, outputs, inputs, timeout) 最后一个是超时,当前连接要是超过这个时间的话,就会 kill

readable , writable , exceptional = select.select(inputs, outputs, inputs)

# When timeout reached , select return three empty lists

if not (readable or writable or exceptional) :

print "Time out ! "

break;

for s in readable :

if s is server:

#通过 inputs 查看是否有客户端来

connection, client_address = s.accept()

print " connection from ", client_address

connection.setblocking(0)

inputs.append(connection)

message_queues[connection] = Queue.Queue()

else:

data = s.recv(1024)

if data :

print " received " , data , "from ",s.getpeername()

message_queues[s].put(data)

# Add output channel for response

if s not in outputs:

outputs.append(s)

else:

#Interpret empty result as closed connection

print " closing", client_address

if s in outputs :

outputs.remove(s)

inputs.remove(s)

s.close()

#清除队列信息

del message_queues[s]

for s in writable:

try:

next_msg = message_queues[s].get_nowait()

except Queue.Empty:

print " " , s.getpeername() , 'queue empty'

outputs.remove(s)

else:

print " sending " , next_msg , " to ", s.getpeername()

os.popen('sleep 5').read()

s.send(next_msg)

for s in exceptional:

print " exception condition on ", s.getpeername()

#stop listening for input on the connection

inputs.remove(s)

if s in outputs:

outputs.remove(s)

s.close()

#清除队列信息

del message_queues[s]

关于 epoll 的方面,大家可以看看这个老外的文档,写不错 ~

select 是轮询、epoll 是触发式的,所以 epoll 的效率高。

下面是用 epoll 实现一个服务端 ~

blog from xiaorui.cc

import socket, select

EOL1 = b'\n\n'

EOL2 = b'\n\r\n'

response = b'HTTP/1.0 200 OK\r\nDate: Mon, 1 Jan 1996 01:01:01 GMT\r\n'

response += b'Content-Type: text/plain\r\nContent-Length: 13\r\n\r\n'

response += b'Hello, world!'

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

serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

serversocket.bind(('0.0.0.0', 8080))

serversocket.listen(1)

serversocket.setblocking(0)

epoll = select.epoll()

epoll.register(serversocket.fileno(), select.EPOLLIN)

try:

connections = {}; requests = {}; responses = {}

while True:

events = epoll.poll(1)

for fileno, event in events:

if fileno == serversocket.fileno():

connection, address = serversocket.accept()

connection.setblocking(0)

epoll.register(connection.fileno(), select.EPOLLIN)

connections[connection.fileno()] = connection

requests[connection.fileno()] = b''

responses[connection.fileno()] = response

elif event & select.EPOLLIN:

requests[fileno] += connections[fileno].recv(1024)

if EOL1 in requests[fileno] or EOL2 in requests[fileno]:

epoll.modify(fileno, select.EPOLLOUT)

connections[fileno].setsockopt(socket.IPPROTO_TCP, socket.TCP_CORK, 1)

print('-'*40 + '\n' + requests[fileno].decode()[:-2])

elif event & select.EPOLLOUT:

byteswritten = connections[fileno].send(responses[fileno])

responses[fileno] = responses[fileno][byteswritten:]

if len(responses[fileno]) == 0:

connections[fileno].setsockopt(socket.IPPROTO_TCP, socket.TCP_CORK, 0)

epoll.modify(fileno, 0)

connections[fileno].shutdown(socket.SHUT_RDWR)

elif event & select.EPOLLHUP:

epoll.unregister(fileno)

connections[fileno].close()

del connections[fileno]

finally:

epoll.unregister(serversocket.fileno())

Epoll 的最大好处是不会随着FD的数目增长而降低效率,在 select 中采用轮询处理,每个 fd 的处理情况,而 epoll 是维护一个队列,直接看队列是不是空就可以了。

在这里也推荐大家用 epoll 写服务端的东西,当然我自己理解的不够好,咱们多交流 !!!

本文出自 “峰云,就她了。” 博客,谢绝转载!



推荐阅读
  • 详解 Python 的二元算术运算,为什么说减法只是语法糖?[Python常见问题]
    原题|UnravellingbinaryarithmeticoperationsinPython作者|BrettCannon译者|豌豆花下猫(“Python猫 ... [详细]
  • 开发笔记:Python之路第一篇:初识Python
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Python之路第一篇:初识Python相关的知识,希望对你有一定的参考价值。Python简介& ... [详细]
  • Python语言简介、环境搭建、PyCharm的安装和配置
    一、Python语言简介1.1Python语言的基本概念官方对Python语言的介绍如下:Python是一款易于学习且功能强大的编程语言。它具有高效率的数据结构,能够简单又有效地实 ... [详细]
  • 前言无论使用哪种语言,我们都需要关注性能优化,提高执行效率。选择脚本语言需要持久的速度。在某种程度上,这句话说明了Python作为一种脚 ... [详细]
  • 代码如下:#coding:utf-8importosimportsysdefcut_and_paste_file(source,destination):”’sourc ... [详细]
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • web.py开发web 第八章 Formalchemy 服务端验证方法
    本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
  • Python爬虫中使用正则表达式的方法和注意事项
    本文介绍了在Python爬虫中使用正则表达式的方法和注意事项。首先解释了爬虫的四个主要步骤,并强调了正则表达式在数据处理中的重要性。然后详细介绍了正则表达式的概念和用法,包括检索、替换和过滤文本的功能。同时提到了re模块是Python内置的用于处理正则表达式的模块,并给出了使用正则表达式时需要注意的特殊字符转义和原始字符串的用法。通过本文的学习,读者可以掌握在Python爬虫中使用正则表达式的技巧和方法。 ... [详细]
  • 树莓派语音控制的配置方法和步骤
    本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
  • 我们需要用到一个python强大的库:python-dox直接pipinstallpython-docx在项目中加个赤壁赋.docx的空文件附上完整的python代码fromdoc ... [详细]
author-avatar
手机用户2602917083
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有