SocketServer는 네트워크 서비스 프레임워크를 생성합니다. 이는 TCP, UDP, UNIX 스트림 및 UNIX 데이터그램을 통한 동기 네트워크 요청을 처리하기 위한 클래스를 정의합니다.
1. 서버 유형
SocketServer에는 5가지 서버 클래스가 있습니다.
1.BaseServer는 API를 정의하며 인스턴스화 및 직접 사용에는 사용되지 않습니다.
2.TCPServer는 TCP/IP 소켓 통신을 위해 사용됩니다.
3.UDPServer는 데이터그램 소켓을 사용합니다.
4.UnixStreamServer 및 UnixDatagramServer는 Unix 도메인 소켓을 사용하며 Unix 플랫폼에서 지능적으로 사용됩니다.
2. 서버 객체
요청한 주소와 요청 처리 클래스(인스턴스가 아님)를 모니터링할 수 있는 서버를 구축합니다.
1.class SocketServer.BaseServer
모듈 내 모든 서버 객체의 슈퍼 클래스로 인터페이스를 정의하며 대부분의 구현은 서브 클래스에서 완료됩니다.
2.BaseServer.fileno
수신 중인 서버를 나타내는 정수 파일 설명자를 반환합니다. 이 함수는 가장 일반적으로 select.select()에 전달되어 여러 서비스가 동일한 프로세스를 모니터링할 수 있도록 합니다.
3.BaseServer.handle_request
단일 요청을 처리하기 위해 이 함수는 다음 메서드를 순차적으로 호출합니다. get_request(), verify_request 및 process_request.
사용자가 handler() 메서드를 제공하고 예외를 발생시키면 handler_error() 메서드가 호출됩니다.
self.timeout 내에 요청이 수신되지 않으면 handler_timeout() 및 handler_request()가 반환됩니다.
4.BaseServer.serve_forever
BaseServer.serve_forever(poll_interval=0.5), 명시적인 shutdown() 요청이 발생할 때까지 요청을 처리합니다. 순환 훈련은 poll_interval 시간마다 종료됩니다. self.timeout을 무시하십시오. 예약된 작업을 사용해야 하는 경우 다른 스레드를 사용해야 합니다.
5.BaseServer.shutdown
은 Serve_forever()에게 루프를 중지하라고 지시합니다.
6.BaseServer.RequestHandlerClass
사용자 요청 핸들러 클래스는 각 요청에 대해 이 클래스의 인스턴스를 생성합니다.
3. 서버 구현
서버를 생성하면 일반적으로 기존 클래스를 재사용하고 사용자 정의 요청 처리 클래스만 제공하면 됩니다. 요구 사항을 충족하지 않는 경우 하위 클래스를 재정의할 수 있는 여러 BaseServer 메서드가 있습니다.
1.verify_request(reqeust, client_address): 부울 값을 반환해야 합니다. True가 반환되면 요청이 처리됩니다. 이 함수는 액세스 제어 서비스를 구현하기 위해 재정의될 수 있습니다.
2.process_request(request, client_address): Finish_request를 호출하여 RequestHandlerClass() 인스턴스를 생성합니다. 필요한 경우 이 함수는 요청을 처리하기 위한 새 프로세스나 코루틴을 생성할 수 있습니다.
3.finish_request(request, client_address): 요청 처리 인스턴스를 생성합니다. 요청을 처리하려면 handler()를 호출하세요.
4. 요청 핸들러
요청 핸들러는 들어오는 요청을 수신하고 수행할 작업을 결정하는 대부분의 작업을 수행합니다. 핸들러는 "프로토콜"(예: HTTP 또는 XML-RPC)에서 소켓 계층을 구현하는 일을 담당합니다. 들어오는 요청 핸들러에서 요청 데이터를 읽고 처리한 후 응답을 작성합니다. 이를 재정의하는 세 가지 방법이 있습니다.
1.setup(): 요청에 대한 요청 핸들러를 준비합니다. 이 핸들은 핸들보다 먼저 초기화되고 실행됩니다.
2.handle(): 실제 요청 작업을 수행합니다. 들어오는 요청을 구문 분석하고, 데이터를 처리하고, 응답을 반환합니다.
3.finish(): 언제든지 생성된 setup()을 정리합니다.
5. 예시
다음 예시는 tcp, udp 및 비동기
1.TCPServer 예시
import SocketServer class MyHandler(SocketServer.BaseRequestHandler): def handle(self): self.data = self.request.recv(1024).strip() print '{} wrote:'.format(self.client_address[0]) print self.data self.request.sendall(self.data.upper()) if __name__ == '__main__': HOST, PORT = 'localhost', 9999 server = SocketServer.TCPServer((HOST, PORT), MyHandler) server.serve_forever()
2. UDPServr 예시
import SocketServer class MyHandler(SocketServer.BaseRequestHandler): def handle(self): data = self.request[0].strip() socket = self.request[1] print '{} wrote:'.format(self.client_address[0]) print data socket.sendto(data.upper(), self.client_address) if __name__ == '__main__': HOST, PORT = 'localhost', 9999 server = SocketServer.UDPServer((HOST, PORT), MyHandler) server.serve_forever()
3. 비동기 예제
ThreadingMixIn 및 ForkingMixIn 클래스를 통해 비동기 처리기를 구성할 수 있습니다.import socket import threading import SocketServer class MyHandler(SocketServer.BaseRequestHandler): def handle(self): data = self.request.recv(1024) curr_thread = threading.current_thread() response = '{}: {}'.format(curr_thread.name, data) self.request.sendall(response) class Server(SocketServer.ThreadingMixIn, SocketServer.TCPServer): pass def 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__': HOST, PORT = 'localhost', 0 server = Server((HOST, PORT), MyHandler) ip, port = server.server_address serer_thread = threading.Thread(target=server.serve_forever) 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() server.server_close()
4.SocketServer는 클라이언트와 서버 간 Non-Blocking 통신을 구현합니다.
(1) 생성 SocketServerTCP 서버
#创建SocketServerTCP服务器: import SocketServer from SocketServer import StreamRequestHandler as SRH from time import ctime host = 'xxx.xxx.xxx.xxx' port = 9999 addr = (host,port) class Servers(SRH): def handle(self): print 'got connection from ',self.client_address self.wfile.write('connection %s:%s at %s succeed!' % (host,port,ctime())) while True: data = self.request.recv(1024) if not data: break print data print "RECV from ", self.client_address[0] self.request.send(data) print 'server is running....' server = SocketServer.ThreadingTCPServer(addr,Servers) server.serve_forever()
from socket import * host = 'xxx.xxx.xxx.xxx' port = 9999 bufsize = 1024 addr = (host,port) client = socket(AF_INET,SOCK_STREAM) client.connect(addr) while True: data = raw_input() if not data or data=='exit': break client.send('%s\r\n' % data) data = client.recv(bufsize) if not data: break print data.strip() client.close()