모델 소개 선택

http://python.jobbole.com/84058/
다 중 재 활용 I/O
간단 한 네트워크 I/O 모델 글 에서 자주 사용 하 는IO모델 을 알 수 있 습 니 다.그 중에서 동기 화 모델 에서 다 중 복용I/O을 사용 하면 서버 의 성능 을 향상 시 킬 수 있다.
다 중 재 활용 모델 에서 자주 사용 되 는 것 은select모델 과poll모델 입 니 다.이 두 개 는 모두 시스템 인터페이스 로 운영 체제 에서 제공한다.물론Pythonselect모듈 은 더욱 고 급 스 러 운 패 키 징 을 진행 하 였 습 니 다.select|poll의 밑바닥 원리 와 차이 가 많 지 않다.다음은select를 소개 합 니 다.
select 원리
네트워크 통신 은Unix시스템 에 의 해 파일 의 읽 기와 쓰기 로 추상 화 되 어 있 으 며,일반적으로 장치 드라이버 에 의 해 제공 되 며,드라이브 는 자신의 데이터 가 사용 가능 한 지 여 부 를 알 수 있 습 니 다.차단 작업 을 지원 하 는 장치 구동 은 보통 읽 기/쓰기 대기 열 이 상층(사용자 층)을 지원 하 는 데 필요 한block또는non-block작업 을 수행 합 니 다.장치 의 파일 자원 이 사용 가능 하 다 면 프로 세 스 를 알 리 고,반대로 프로 세 스 를 잠 들 게 하 며,데이터 가 사용 가능 할 때 까지 기 다 렸 다가 프로 세 스 를 깨 웁 니 다.
이 장치 의 파일 설명 자 는 한 배열 에 놓 여 있 습 니 다.그리고select호출 할 때 이 배열 을 옮 겨 다 니 며 파일 설명 자 를 읽 을 수 있다 면 파일 설명 자 를 되 돌려 줍 니 다.옮 겨 다 니 기 가 끝 난 후에 도 사용 가능 한 장치 파일 설명자 가 없 으 면select사용자 프로 세 스 는 잠 을 잘 수 있 습 니 다.자원 이 사용 가능 할 때 깨 울 때 까지 감시 하 는 배열 을 옮 겨 다 닙 니 다.매번 옮 겨 다 닐 때마다 선형 이다.
select 리 턴 서버select시스템 호출 과 운영 체제 에 관 한 지식 이 있 기 때문에 말 그대로 그 원 리 를 이해 하 는 것 이 지루 합 니 다.코드 로 보 여 주 는 게 좋 을 것 같 아 요.pythonselect모듈 을 사용 하면 다음 리 턴 서버 를 쉽게 쓸 수 있 습 니 다:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
import selectimport socketimport sys HOST = 'localhost'PORT = 5000BUFFER_SIZE = 1024 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server.bind((HOST, PORT))server.listen(5) inputs = [server, sys.stdin]running = True while True:    try:        # select 함수 호출,대기 차단        readable, writeable, exceptional = select.select(inputs, [], [])    except select.error, e:        break     # 데이터 도착,순환    for sock in readable:        # 연결 만 들 기        if sock == server:            conn, addr = server.accept()            # select 감청 socket            inputs.append(conn)        elif sock == sys.stdin:            junk = sys.stdin.readlines()            running = False        else:            try:                # 클 라 이언 트 연결 에서 보 낸 데이터 읽 기                data = sock.recv(BUFFER_SIZE)                if data:                    sock.send(data)                    if data.endswith('\r\r'):                        # select 감청 socket 제거                        inputs.remove(sock)                        sock.close()                else:                    # select 감청 socket 제거                    inputs.remove(sock)                    sock.close()            except socket.error, e:                inputs.remove(sock) server.close()
상기 코드 를 실행 하고curl방문http://localhost:5000을 사용 하면 명령 행 이 요청 한HTTP request정 보 를 되 돌려 줍 니 다.
다음은 상술 한 코드 의 원 리 를 상세 하 게 분석한다.
123
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server.bind((HOST, PORT))server.listen(5)
상기 코드 는socketTCP소켓 을 초기 화하 고 호스트 주소 와 포트 를 연결 한 다음 서버 감청 을 설정 합 니 다.
1
inputs = [server, sys.stdin]
이것 은select감청 이 필요 한 목록 을 정의 합 니 다.목록 에는 감청 이 필요 한 대상(시스템 감청 과 같은 파일 설명자)이 있 습 니 다.여기 감청socket소켓 과 사용자 의 입력 입 니 다.
그리고 코드 는 서버 무선 순환 을 합 니 다.
12345
try:    # select 함수 호출,대기 차단    readable, writeable, exceptional = select.select(inputs, [], [])except select.error, e:    break select함 수 를 호출 하여 감청 이 들 어 오 는 목록 을 반복 하기 시 작 했 습 니 다inputs.curl서버 가 없 으 면tcp클 라 이언 트 연결 이 되 지 않 았 기 때문에 목록 에 있 는 대상 은 모두 데이터 자원 으로 사용 할 수 없습니다.그래서select차단 되 어 돌아 오지 않 습 니 다.
클 라 이언 트 입력curl http://localhost:5000이후 하나의 소켓 통신 이 시작 되 었 습 니 다.이때input의 첫 번 째 대상server사용 할 수 없 는 것 에서 사용 할 수 있 습 니 다.따라서select함수 호출 이 되 돌 아 왔 습 니 다.이때readable소켓 대상(파일 설명자 읽 을 수 있 음)이 있 습 니 다.
123456
for sock in readable:    # 연결 만 들 기    if sock == server:        conn, addr = server.accept()        # select 감청 socket        inputs.append(conn) select돌아 온 후 읽 을 수 있 는 파일 대상 을 옮 겨 다 닙 니 다.이 때 읽 을 수 있 는 소켓 연결 은 하나 뿐 입 니 다.소켓 을 호출 하 는accept()방법 은TCP세 번 악수 하 는 연결 을 만 든 다음 이 연결 대상 을inputs감시 목록 에 추가 하여 이 연결 에 데이터 가 있 는 지 확인 하 겠 습 니 다IO작업.
이 때readable사용 가능 한 대상 이 하나 밖 에 없 기 때문에 옮 겨 다 니 기 가 끝 났 습 니 다.다시 주 순환 으로 돌아 가select를 다시 호출 합 니 다.이 때 호출 할 때 새로운 연결 이 필요 한 지 여 부 를 감시 할 뿐만 아니 라 방금 추 가 된 연결 도 감시 합 니 다.curl의 데이터 가 도착 하면select다시readable로 돌아 갑 니 다.이 때for순환 을 진행 합 니 다.새 소켓 이 없 으 면 다음 코드 를 실행 합 니 다:
123456789101112131415
try:    # 클 라 이언 트 연결 에서 보 낸 데이터 읽 기    data = sock.recv(BUFFER_SIZE)    if data:        sock.send(data)        if data.endswith('rnrn'):            # select 감청 socket 제거            inputs.remove(sock)            sock.close()    else:        # select 감청 socket 제거        inputs.remove(sock)        sock.close()except socket.error, e:    inputs.remove(sock)
소켓 연결 을 통 해recv함 수 를 호출 하고 클 라 이언 트 가 보 낸 데 이 터 를 가 져 옵 니 다.데이터 전송 이 완료 되면 감시 하 는inputs목록 에서 이 연결 을 제거 합 니 다.연결 을 닫 습 니 다.
전체 네트워크 인 터 랙 션 과정 은 이 렇 습 니 다.물론 여기 서 사용자 가 명령 행 에 입력 이 중단 되면inputs목록 에서 감시 하 는sys.stdinselect를 되 돌려 주 고 마지막 으로 다음 코드 를 실행 합 니 다.
123
elif sock == sys.stdin:    junk = sys.stdin.readlines()    running = False
프로그램 처리sock연결 할 때curl를 다시 입력 했다 고 가정 하면 서버 요청 은 어떻게 됩 니까?이 때 는 의심의 여지 가 없습니다.inputs안의server소켓 이 사용 가능 합 니 다.현재for순환 처리 가 완료 되면select호출 은server로 돌아 갑 니 다.inputs에 이전 과정의conn연결 이 있다 면inputs를 순환 적 으로 옮 겨 다 닐 때 새로운 소켓accept|inputs목록 을 감시 한 다음 이전conn연결 을 계속 순환 처리 합 니 다.for순환 이 끝 날 때 까지 주 순환 호출select에 들 어 갑 니 다.
언제든지inputs감청 대상 에 데이터 가 있 습 니 다.다음 호출select이 있 을 때 는readable로 돌아 갑 니 다.돌아 오기 만 하면readable|for순환 을 진행 합 니 다.for순환 이 끝 날 때 까지 다음select를 진행 합 니 다.
소켓 연결 은IO이 며,연결 데이터 가 도착 하 는 것 도IO입 니 다.
select 의 부족select사용 하기에 시원 하고 크로스 플랫폼 의 특성 에 도 불구 하고.하지만select문제 가 있 습 니 다.select감시 할 파일 설명자 가 필요 하 며,이 설명자 의 배열 은 가장 큰 제한 이 있 습 니 다.파일 설명자 의 수량 이 증가 함 에 따라 사용자 상태 와 커 널 의 주소 공간의 복사 로 인 한 비용 도 선형 으로 증가 할 것 이다.감시 하 는 파일 설명자 가 오랫동안 활성화 되 지 않 더 라 도select선형 스 캔 을 합 니 다.
이러한 문 제 를 해결 하기 위해 운영 체 제 는poll방안 을 제 공 했 지만poll모델 은select와 대체적으로 비슷 하고 제한 만 바 뀌 었 다.현재Linux가장 선진 적 인 방식 은epoll모델 입 니 다.
많은 고성능 소프트웨어,예 를 들 어nginxnodejs모두epoll를 바탕 으로 하 는 비동기 입 니 다.

좋은 웹페이지 즐겨찾기