socketserver 원본 읽기 노트
socketserver는python3의 새로운 이름으로python2에서 SocketServer라고 하는데 이번에 읽은 것은 0.4버전입니다.
이 프레임워크는 주로 ServerClass와 RequestHandlerClass 두 종류를 사용한다.
BaseServer
추상적 기류TCPServer
처리 흐름식 플러그인UnixStreamServer
로컬 처리 스트림 소켓 처리, UNIX 플랫폼만 적용UDPServer
처리 데이터 패키지 UnixDatagramServer
로컬 처리 데이터 보고 소켓을 처리하고 UNIX 플랫폼만 적용BaseRequestHandler
처리기류StreamRequestHandler
처리 흐름식 플러그인DatagramRequestHandler
처리 데이터 패키지 MixINClass
ForkingMixIn
다중 프로세스를 이용하여 비동기화를 실현하고 요청을 받은 후fork한 프로세스가 응답 처리ThreadingMixIn
다중 스레드를 이용하여 이상을 실현하고 요청을 받은 후 하나의 스레드를 사용하여 응답 처리Server 클래스의 상속 관계
+------------+
| BaseServer |
+------------+
|
v
+-----------+ +------------------+
| TCPServer |------->| UnixStreamServer |
+-----------+ +------------------+
|
v
+-----------+ +--------------------+
| UDPServer |------->| UnixDatagramServer |
+-----------+ +--------------------+
UDPSERver는 TCPServer를 계승하고, TCPServer는 BaseServer를 계승하며, UnixStreamServer는 TCPServer를 계승하고, UnixDatagramServer는 UDPSERver를 계승한다.
if hasattr(socket, 'AF_UNIX'):
class UnixStreamServer(TCPServer):
address_family = socket.AF_UNIX
class UnixDatagramServer(UDPServer):
address_family = socket.AF_UNIX
원본 코드를 보면 Unix Stream Server와 TCPServer, Unix Datagram Server와 UDPSERver는 단지 바뀌었다
address_family
.소켓에 관하여.AF_UNIX는 주로 같은 기기의 프로세스 간 통신에 사용됩니다.AF_INET 도메인 및 AF_UNIX 도메인 소켓 통신 원리 비교
if hasattr(os, "fork"):
class ForkingUDPServer(ForkingMixIn, UDPServer): pass
class ForkingTCPServer(ForkingMixIn, TCPServer): pass
class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass
다중 프로세스 서버와 다중 스레드 서버는 TCPServer, UDPSERver와 Forking MixIn, Threading MixIn을 조합한 것일 뿐이다.
class BaseRequestHandler:
def __init__(self, request, client_address, server):
self.request = request
self.client_address = client_address
self.server = server
self.setup()
try:
self.handle()
finally:
self.finish()
def setup(self):
pass
def handle(self):
pass
def finish(self):
pass
RequestHandler 클래스의 상속 관계
+--------------------+ +----------------------+
| BaseRequestHandler |------->| StreamRequestHandler |
+--------------------+ +----------------------+
|
v
+------------------------+
| DatagramRequestHandler |
+------------------------+
Stream Request Handler와 Datagram Request Handler는 Base Request Handler를 계승하는 것으로 setup과finish를 다시 썼고 본질적으로 캐시로 플러그인에 대한 서비스를 제공합니다.
호출 프로세스
예를 들어 호출 절차를 보다
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0]))
print(self.data)
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
server.serve_forever()
여기에는 BaseRequestHandler로부터 계승된 MyTCPHandler를 정의하고 Handle 방법을 다시 쓴 다음 호스트, 포트와 함께 TCPServer로 전송합니다.
class BaseServer:
def __init__(self, server_address, RequestHandlerClass):
"""Constructor. May be extended, do not override."""
self.server_address = server_address
self.RequestHandlerClass = RequestHandlerClass
self.__is_shut_down = threading.Event()
self.__shutdown_request = False
class TCPServer(BaseServer):
def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
"""Constructor. May be extended, do not override."""
BaseServer.__init__(self, server_address, RequestHandlerClass)
self.socket = socket.socket(self.address_family,
self.socket_type)
if bind_and_activate:
try:
self.server_bind()
self.server_activate()
except:
self.server_close()
raise
1. TCPServer 실례화는 자체
server_bind()
방법을 호출하여 전송된 server_address
파라미터를 귀속시켰고, server_activate()
방법은 BaseServer
클래스에서 다시 쓰는 것으로 주로 요청 대기열 크기의 설정입니다.2. 서비스를 시작하고
BaseServer
류의 serve_forever()
방법을 호출하여 요청을 끊임없이 감청하고 요청이 있을 때 _handle_request_noblock()
방법으로 요청 처리를 완성한 다음에 service_actions()
처리 후의 조작을 호출한다.이 방법은 ForkingMixIn
클래스에서 다시 작성되어 요청 처리를 완료하는 프로세스를 해결하는 데 사용됩니다. def _handle_request_noblock(self):
try:
request, client_address = self.get_request()
except OSError:
return
if self.verify_request(request, client_address):
try:
self.process_request(request, client_address)
except Exception:
self.handle_error(request, client_address)
self.shutdown_request(request)
except:
self.shutdown_request(request)
raise
else:
self.shutdown_request(request)
_handle_request_noblock()
메서드가 요청을 처리할 때 다음 메서드가 호출됩니다.get_request()
방법은 TCPServer
류에서 정의, 호출socket.accept()
방법, 반환request
파라미터와 client_address
파라미터verify_request(request, client_address)
방법은 BaseServer
클래스에서 정의되고 하위 클래스에서 다시 써서 검증 처리를 할 수 있다process_request(request, client_address)
방법 요청 처리 함수, 호출finish_request()
방법, ForkingMixIn
류와 ThreadingMixIn
류에서 다시 쓰기, 프로세스나 루틴으로 처리finish_request(request, client_address)
방법의 구체적인 요청 처리 과정, 여기는 사용자 정의MyTCPHandler
클래스의 실례화입니다. 이 클래스는 BaseRequestHandler
클래스를 계승하고 그 정의를 따르며 자신이 실례화될 때 handle()
방법shutdown_request(request)
방법은 TCPServer
류에서 정의되고 먼저 request.shutdown(socket.SHUT_WR)
, 오류가 발생하면 close_request(request)
방법으로 request.close()
한다. UDPServer
류에서 이 함수는 다시 쓴다pass
떨어진다BaseServer
클래스의 shutdown()
방법을 호출할 수 있습니다. 예를 들어 직접 사용Ctrl-C
def shutdown(self):
self.__shutdown_request = True
self.__is_shut_down.wait()
주로
__shutdown_request
표지 교체, 대기 차단serve_forever()
라인 복귀이것이 예제
TCPServer
의 라이프 사이클입니다.약간의 문제
request.shutdowm(socket.SHUT_WR)
과request.close()
차이1. shutdown을 호출하면 지정한 링크를 닫고,close는 설명자의 인용 계수기가 0일 때까지 기다려야 링크를 닫습니다. 2.close는 두 개의 링크를 동시에 닫고, shutdown 값은 지정한 링크를 닫습니다.close 후 파일 설명자는 더 이상 사용할 수 없습니다. (인용 기수는 0이고 자원 방출), shutdown 후 파일 설명자는 사용할 수 있습니다.
구체적이다
if hasattr(selectors, 'PollSelector'):
_ServerSelector = selectors.PollSelector
else:
_ServerSelector = selectors.SelectSelector
## Lib/selectors.py
# Choose the best implementation, roughly:
# epoll|kqueue|devpoll > poll > select.
# select() also can't accept a FD > FD_SETSIZE (usually around 1024)
if 'KqueueSelector' in globals():
DefaultSelector = KqueueSelector
elif 'EpollSelector' in globals():
DefaultSelector = EpollSelector
elif 'DevpollSelector' in globals():
DefaultSelector = DevpollSelector
elif 'PollSelector' in globals():
DefaultSelector = PollSelector
else:
DefaultSelector = SelectSelector
cketserver 모듈에서 수동으로 poll 라이브러리를 선택했습니다. 모듈이 제공하는 Default Selector를 사용하여 선택하는 것이 아닙니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.