>백엔드 개발 >파이썬 튜토리얼 >SocketServer 모듈을 사용하여 Python으로 기본 서버 프로그램을 작성하는 방법에 대한 튜토리얼

SocketServer 모듈을 사용하여 Python으로 기본 서버 프로그램을 작성하는 방법에 대한 튜토리얼

WBOY
WBOY원래의
2016-08-04 08:55:431553검색

SocketServer는 네트워크 서버 작성을 단순화합니다. 여기에는 TCPServer, UDPServer, UnixStreamServer, UnixDatagramServer의 4가지 클래스가 있습니다. 이 네 가지 클래스는 동기식으로 처리되며 비동기식은 ForkingMixIn 및 ThreadingMixIn 클래스를 통해 지원됩니다.

서버 생성 단계. 먼저 BaseRequestHandler를 하위 클래스로 만들고 해당 핸들() 메서드를 재정의하는 요청 처리 클래스를 만들어야 합니다. 둘째, 서버의 주소와 요청 처리기 클래스를 전달하여 서버 클래스를 인스턴스화해야 합니다. 마지막으로, handler_request()(보통 다른 이벤트 루프를 호출하거나 select() 사용) 또는 Serve_forever()를 호출합니다.

ThreadingMixIn 클래스를 통합할 때 예외 닫기를 처리해야 합니다. daemon_threads는 스레드가 종료될 때까지 서버가 대기할지 여부를 나타냅니다. 스레드가 서로 독립적인 경우 기본값은 False로 설정되어야 합니다.

어떤 네트워크 프로토콜을 사용하든 서버 클래스는 동일한 외부 메서드와 속성을 갖습니다.

Python3에서 이 모듈은 소켓서버 모듈입니다. Python 2에서 이 모듈은 SocketServer 모듈입니다. 따라서 import를 이용하여 import하는 경우에는 상황에 맞게 import를 하여야 하며, 그렇지 않으면 오류가 발생하게 됩니다. 가져온 코드는 다음과 같습니다.

try:
  import socketserver   #Python 3
except ImportError:
  import SocketServer   #Python 2

SocketSerror 모듈에는 TCP, UDP 및 UNIX 도메인 소켓 서버 구현을 단순화하는 많은 클래스가 포함되어 있습니다.

1. 처리절차
이 모듈을 사용하려면 기본 클래스 BaseRequestHandler에서 상속되는 핸들러 클래스를 정의해야 합니다. BaseRequestHandler 클래스의 인스턴스 h는 다음 메서드를 구현할 수 있습니다.
1. h.handle() 실제 요청 작업을 수행하려면 이 메서드를 호출합니다. 이 함수는 매개변수 없이 호출할 수 있지만 여러 인스턴스 변수에는 유용한 값이 포함되어 있습니다. h.request에는 요청이 포함되고, h.client_address에는 클라이언트 주소가 포함되며, h.server에는 핸들러를 호출한 인스턴스가 포함됩니다. TCP와 같은 데이터 스트리밍 서비스의 경우 h.request 속성은 소켓 개체입니다. 데이터그램 서비스의 경우 수신된 데이터가 포함된 바이트 문자열입니다.
2. h.setup() 이 메소드는 handler() 이전에 호출됩니다. 기본적으로는 아무 작업도 수행하지 않습니다. 서버에서 추가 연결 설정(예: SSL 연결 설정)을 구현하도록 하려면 여기에서 수행할 수 있습니다.
3. h.finish() handler()를 실행한 후 정리 작업을 수행하려면 이 메서드를 호출합니다. 기본적으로는 아무 작업도 수행하지 않습니다. setup() 및 handler() 메서드 모두 예외를 생성하지 않으면 이 메서드를 호출할 필요가 없습니다.
애플리케이션이 스트림 지향 연결(예: TCP)만 조작할 수 있다는 것을 알고 있다면 BaseRequestHandler 대신 StreamRequestHandler에서 상속해야 합니다. StreamRequestHandler 클래스는 두 가지 속성을 설정합니다. h.wfile은 클라이언트에 데이터를 쓰는 파일 형식의 개체이고, h.rfile은 클라이언트에서 데이터를 읽는 파일 형식의 개체입니다.
패킷에 대해 작동하고 지속적으로 보낸 사람에게 응답을 반환하는 핸들러를 작성하려면 DatagramRequestHandler에서 상속해야 합니다. 제공하는 클래스 인터페이스는 StramRequestHandler와 동일합니다.

2. 서버
핸들러를 사용하려면 서버 개체에 삽입해야 합니다. 네 가지 기본 서버 클래스가 정의됩니다.
(1) TCPServer(address,handler)는 IPv4의 TCP 프로토콜을 사용하는 서버를 지원합니다. 주소는 (호스트, 포트) 튜플입니다. 핸들러는 BaseRequestHandler 또는 StreamRequestHandler 클래스의 하위 클래스 인스턴스입니다.
(2) UDPServer(address,handler)는 IPv4의 UDP 프로토콜을 사용하는 서버를 지원합니다. 주소와 핸들러는 TCPServer와 유사합니다.
(3) UnixStreamServer(address,handler)는 UNIX 도메인 소켓을 사용하여 TCPServer에서 상속된 데이터 스트림 프로토콜 지향 서버를 구현합니다.
(4) UnixDatagramServer(address,handler) UDPServer로부터 상속받은 데이터그램 프로토콜을 구현하기 위해 UNIX 도메인 소켓을 사용하는 서버입니다.
네 가지 서버 클래스 모두의 인스턴스에는 다음과 같은 메서드와 변수가 있습니다.
1. s.socket 들어오는 요청에 사용되는 소켓 개체입니다.
2. s.sever_address 수신 서버의 주소입니다. 튜플("127.0.0.1",80)
등 3. s.RequestHandlerClass 서버 생성자에 전달되고 사용자가 제공하는 요청 핸들러 클래스입니다.
4. s.serve_forever()는 무제한 요청을 처리합니다
5. s.shutdown() Serve_forever() 루프를 중지합니다
6. s.fileno() 서버 소켓의 정수 파일 설명자를 반환합니다. 이 방법은 select() 함수와 같은 폴링 작업을 통해 서버 인스턴스를 효과적으로 사용합니다.

三、定义自定义服务器
服务器往往需要特殊的配置来处理不同的网络地址族、超时期、并发和其他功能,可以通过继承上面四个基本服务器类来自行定义。
可以通过混合类获得更多服务器功能,这也是通过进程或线程分支添加并发行的方法。为了实现并发性,定义了以下类:
(1)ForkingMixIn         将UNIX进程分支添加到服务器的混合方法,使用该方法可以让服务器服务多个客户。
(2)ThreadingMixIn    修改服务器的混合类,可以使用线程服务多个客户端。
要向服务器添加这些功能,可以使用多重继承,其中首先列出混了类。
由于并发服务器很常用,为了定义它,SocketServer预定义了以下服务器类:
(1)ForkingUDPServer(address,handler)  
(2)ForkingTCPServer(address,handler)
(3)ThreadingUDPServer(address,handler)
(4)ThreadingTCPServer(address,handler)
上面有点乱,现总结以下:
SocketServer模块中的类主要有以下几个:
1、BaseServer    包含服务器的核心功能与混合类(mix-in)的钩子功能。这个类主要用于派生,不要直接生成这个类的类对象,可以考虑使用TCPServer和UDPServer类。
2、TCPServer    基本的网络同步TCP服务器
3、UDPServer    基本的网络同步UDP服务器
4、ForkingMixIn   实现了核心的进程化功能,用于与服务器类进行混合(mix-in),以提供一些异步特性。不要直接生成这个类的对象。
5、ThreadingMixIn   实现了核心的线程化功能,用于与服务器类进行混合(mix-in),以提供一些异步特性。不要直接生成这个类的对象。
6、ForkingTCPServer     ForkingMixIn与TCPServer的组合
7、ForkingUDPServer    ForkingMixIn与UDPServer的组合
8、BaseRequestHandler
9、StreamRequestHandler    TCP请求处理类的一个实现
10、DataStreamRequestHandler   UDP请求处理类的一个实现
现在繁杂的事务都已经封装到类中了,直接使用类即可。

四、实例
1.使用SocketServer模块编写的TCP服务器端代码:

#! /usr/bin/env python
#coding=utf-8
"""使用SocketServer来实现简单的TCP服务器"""
from SocketServer import (TCPServer,StreamRequestHandler as SRH)
from time import ctime
class MyRequestHandler(SRH):
  def handle(self):
    print "connected from ",self.client_address
    self.wfile.write("[%s] %s" %(ctime(),self.rfile.readline()))
tcpSer=TCPServer(("",10001),MyRequestHandler)
print "waiting for connection"
tcpSer.serve_forever()
相应的TCP客户端代码:
#! /usr/bin/env python
#coding=utf-8
from socket import *
BUFSIZE=1024
#每次都要创建新的连接
while True:
  tcpClient=socket(AF_INET,SOCK_STREAM)
  tcpClient.connect(("localhost",10001))
  data=raw_input(">")
  if not data:
    break
  tcpClient.send("%s\r\n" %data)
  data1=tcpClient.recv(BUFSIZE)
  if not data1:
    break
  print data1.strip()
  tcpClient.close()

2.异步服务器的实现

ThreadingMixIn的例子:

import socketimport threadingimport SocketServerclass ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):

  def handle(self):
    data = self.request.recv(1024)
    cur_thread = threading.current_thread()
    response = "{}: {}".format(cur_thread.name, data)
    self.request.sendall(response)class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
  passdef client(ip, port, message):
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  sock.connect((ip, port))
  try:
    sock.sendall(message)
    response = sock.recv(1024)
    print "Received: {}".format(response)
  finally:
    sock.close()if __name__ == "__main__":
  # Port 0 means to select an arbitrary unused port
  HOST, PORT = "localhost", 0

  server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
  ip, port = server.server_address  # Start a thread with the server -- that thread will then start one
  # more thread for each request
  server_thread = threading.Thread(target=server.serve_forever)
  # Exit the server thread when the main thread terminates
  server_thread.daemon = True
  server_thread.start()
  print "Server loop running in thread:", server_thread.name

  client(ip, port, "Hello World 1")
  client(ip, port, "Hello World 2")
  client(ip, port, "Hello World 3")

  server.shutdown()

执行结果:

$ python ThreadedTCPServer.py
Server loop running in thread: Thread-1
Received: Thread-2: Hello World 1
Received: Thread-3: Hello World 2
Received: Thread-4: Hello World 3

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