백엔드 개발 파이썬 튜토리얼 Python中使用select模块实现非阻塞的IO

Python中使用select模块实现非阻塞的IO

Jun 06, 2016 am 11:21 AM
io python 비차단

Socket的英文原义是“孔”或“插座”。作为BSD UNIX的进程通信机制,取后一种意思。通常也称作”套接字”,用于描述IP地址和端口,是一个通信链的句柄。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原意那样,像一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电, 有的提供110伏交流电,有的则提供有线电视节目。 客户软件将插头插到不同编号的插座,就可以得到不同的服务。–百度百科

socket如此重要,现在的网络编程几乎都是用的它,它起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用打开,读写,关闭的模式来操作。然而,对于网络服务来说,往往针对大量的客户群体,例如web,对于这类服务,必须要保证既能并行处理请求,又能保证服务的稳定。但传统的socket在处理并发方面有所欠缺,借助与select模块,能够较好的是要非阻塞的IO。

Python中的select模块以列表形式接受四个参数,分别是需要监控的可读文件对象,可写文件对象,产生异常的文件对象和超时设置,当监控的对象发生变化时,select会返回发生变化的对象列表。下面是用select实现一个简单的聊天室:

#!/usr/bin/env python
#*-* coding:utf-8 *-*
import socket
import select
import sys
import signal
class ChatServer():
  def __init__(self,host,port,timeout=10,backlog=5):
    #记录连接的客户端数量
    self.clients =0
    #存储连接的客户端socket和地址对应的字典
    self.clientmap={}
    #存储连接的客户端socket
    self.outputs = []
    #建立socket
    self.server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    self.server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    self.server.bind((host,port))
    self.server.listen(backlog)
    #增加信号处理
    signal.signal(signal.SIGINT,self.sighandler) 
  def sighandler(self):
    sys.stdout.write("Shutdown Server......\n")
    #向已经连接客户端发送关系信息,并主动关闭socket
    for output in self.outputs:
      output.send("Shutdown Server")
      output.close()
    #关闭listen
    self.server.close()
    sys.stdout.flush()
  #主函数,用来启动服务器
  def run(self):
    #需要监听的可读对象
    inputs=[self.server]
    
    runing=True
    #添加监听主循环
    while runing:
      try:
        readable,writeable,exceptional = select.select(inputs,self.outputs,[])
        #此处会被select模块阻塞,只有当监听的三个参数发生变化时,select才会返回
      except select.error,e:
        break
      #当返回的readable中含有本地socket的信息时,表示有客户端正在请求连接
      if self.server in readable:
        #接受客户端连接请求
        client,addr=self.server.accept()
        sys.stdout.write("New Connection from %s\n"%str(addr))
        sys.stdout.flush()
        #更新服务器上客户端连接情况
        #1,数量加1
        #2,self.outputs增加一列
        #3,self.clientmap增加一对
        #4, 给input添加可读监控
        self.clients += 1
        self.outputs.append(client)
        self.clientmap[client]=addr
        inputs.append(client)
      
      #readable中含有已经添加的客户端socket,并且可读
      #说明 1,客户端有数据发送过来或者 2,客户端请求关闭
      elif len(readable) != 0:
        #1, 取出这个列表中的socket
        csock=readable[0]
        #2, 根据这个socket,在事先存放的clientmap中,去除客户端的地址,端口的详细信息
        host,port = self.clientmap[csock]
        #3,取数据, 或接受关闭请求,并处理
        #注意,这个操作是阻塞的,但是由于数据是在本地缓存之后,所以速度会非常快
        try:
          data = csock.recv(1024).strip()
          for cs in self.outputs:
            if cs != csock:
              cs.send("%s\n"%data)
        except socket.error,e:
          self.clients -= 1
          inputs.remove(csock)
          self.outputs.remove(csock)
          del self.clientmap[csock]
      #print self.outputs
    self.server.close()
        
if __name__ == "__main__":
  chat=ChatServer("",8008)
  chat.run()

로그인 후 복사

运行这个脚本,然后用任意客户端如telnet或netcat连接8008端口,多个客户端之间就可以进行对话。

其实select模块本身是阻塞的,当需要监控的socket发生变化时,select作出返回,下面的程序会继续执行,程序根据select的返回值,对各种情况作出处理。

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Linux 시스템에서 Python 통역사를 삭제할 수 있습니까? Linux 시스템에서 Python 통역사를 삭제할 수 있습니까? Apr 02, 2025 am 07:00 AM

Linux 시스템과 함께 제공되는 Python 통역사를 제거하는 문제와 관련하여 많은 Linux 배포판이 설치 될 때 Python 통역사를 사전 설치하고 패키지 관리자를 사용하지 않습니다 ...

파이썬에서 맞춤형 데코레이터의 Pylance 유형 감지 문제를 해결하는 방법은 무엇입니까? 파이썬에서 맞춤형 데코레이터의 Pylance 유형 감지 문제를 해결하는 방법은 무엇입니까? Apr 02, 2025 am 06:42 AM

Pylance 유형 감지 문제 솔루션 Python 프로그래밍에서 사용자 정의 데코레이터를 사용할 때 Decorator는 행을 추가하는 데 사용할 수있는 강력한 도구입니다 ...

Python 3.6 피클 파일로드 오류 modulenotfounderRor : 피클 파일 '__builtin__'를로드하면 어떻게해야합니까? Python 3.6 피클 파일로드 오류 modulenotfounderRor : 피클 파일 '__builtin__'를로드하면 어떻게해야합니까? Apr 02, 2025 am 06:27 AM

Python 3.6에 피클 파일 로딩 3.6 환경 오류 : ModulenotFounderRor : nomodulename ...

Fastapi와 Aiohttp는 동일한 글로벌 이벤트 루프를 공유합니까? Fastapi와 Aiohttp는 동일한 글로벌 이벤트 루프를 공유합니까? Apr 02, 2025 am 06:12 AM

파이썬 비동기 라이브러리 사이의 호환성 문제 파이썬에서 비동기 프로그래밍은 동시성과 I/O의 프로세스가되었습니다 ...

Python 3.6에 피클 파일을로드 할 때 '__builtin__'모듈을 찾을 수없는 경우 어떻게해야합니까? Python 3.6에 피클 파일을로드 할 때 '__builtin__'모듈을 찾을 수없는 경우 어떻게해야합니까? Apr 02, 2025 am 07:12 AM

Python 3.6에 피클 파일로드 3.6 환경 보고서 오류 : modulenotfounderror : nomodulename ...

파이썬에서 신호를 통해 부모 프로세스를 죽인 후 아동 프로세스가 종료되도록하는 방법은 무엇입니까? 파이썬에서 신호를 통해 부모 프로세스를 죽인 후 아동 프로세스가 종료되도록하는 방법은 무엇입니까? Apr 02, 2025 am 06:39 AM

아동 프로세스의 문제와 해결책은 신호를 사용하여 부모 프로세스를 죽일 때 계속 실행됩니다. Python 프로그래밍에서 신호를 통해 부모 프로세스를 죽인 후에도 아동 프로세스는 여전히 ...

See all articles