큰 작업 - 4 서버 구현

4036 단어
앞에는 분석도 디자인도 있는데 이 단계에 이르면 모든 것이 코드에 구현되어 진정으로 사용할 수 있는 서버가 될 것이다.

KeepList 구성 요소

class Connection(object):
    #  list 
    # KeepList remove , 
    #  , 
    client = KeepList()

지난번에 말했듯이 연결 실례의 저장 방식은 특수한 기능이 있는list이다.자연python은 이런 이상한 기능을 가진 라이브러리가 없기 때문에 우리 스스로 실현해야 한다.
나머지 항목의 위치를 변경하지 않는 기능을 삭제하기 위해 삭제된 위치를 None으로 지정할 수 있습니다.그러나 이로 인해list의 크기가 무한히 커지는 위험이다. 즉, 매번 새로운 노드는list의 끝에 증가하고list의 길이를 증가하지만 삭제는list를 감소시키지 않는다.따라서 이 위험을 해결하기 위해서는 추가할 때마다 원래 삭제된 위치를 먼저 고려해야 한다.삽입할 때마다list를 한 번씩 반복하는 것도 현실적이지 않기 때문에 더 좋은 알고리즘이 필요하다.
이러한 기능을 실현하기 위해 저는 체인 테이블과 유사한 구조를 사용하여 빠른 삭제와 빠른 삽입 기능을 실현하고자 합니다.구체적으로 말하면 데이터list와 같은 길이의 또 다른 아래 표시list를 사용하여 그 중의 모든 항목과 일일이 대응한다.아래 표시된list의 모든 위치의 가능한 값은 -1~len(list)-1입니다. 즉, 데이터list의 모든 항목의 아래 표시에 빈 표시를 추가합니다.
아래 표시list가 하는 역할은 아래 표시를 통해 삭제된 모든 위치를 연결시키는 것입니다.어떤 항목 아래에 표시된list에 대응하는 항목이 -1이면 이 위치가 비어 있음을 나타낸다.값이 있으면, 현재 항목이 삭제되었음을 설명하고, 다음 삭제된 항목은list가 가리키는 항목입니다.이로써 삭제된 모든 노드는 이list에 의해 하나의 체인 테이블로 연결되며, 사용할 때마다 체인 헤더에 접근하면 된다.
노드를 삽입할 때마다 체인 헤더가 노드를 가리키는지 확인한 다음 끝에 추가할지 빈칸을 채울지 선택합니다.삭제할 때마다 체인 헤더를 직접 업데이트합니다. 체인 헤더 앞에 새로운 노드를 삽입하고 헤더를 업데이트합니다.
이렇게 하면 가장 먼저 삽입된 새 노드가 가장 최근에 삭제된 위치에서 삭제 순서와 일치하지 않게 된다.그러나 이 프로젝트에 필요한 것은 고정된 하표일 뿐이고 하표의 크기에 관심이 없기 때문에 이 방법은 실행할 수 있다.

메시지 전달


전체 시스템은 json 형식으로 메시지 전달을 선택한다. 이것은 전송 데이터의 군더더기를 초래할 수 있지만 현재 프로젝트 규모에 있어 필요한 것은 용이성과 좋은 확장성이다.이것은 모두 json이 가지고 있는 특성이다.
메시지의 전달은 본 서버의 가장 중요한 부분이다. 관련된 알고리즘은 많지 않지만 권한 검출 등에 대해서는 조심해야 한다.

웹 페이지


웹 페이지의 논리는 js로 작성됩니다.전체 시스템에서 웹 페이지는 사용자가 접촉하는 층으로서 그 주요 신분은 요청의 발기자와 결과의 수신자이다.
우선, 발기자로서 모니터링해야 할 것은 브라우저의 키 메시지이고, 브라우저와 구축된 웹소켓 연결을 통해 키 메시지를 보내는 것이다.브라우저에는 JSON 모듈이 내장되어 있어 json을 쉽게 수발할 수 있습니다.
또한 socket가 연결을 구축한 후 http 요청과 같은 일발일수 기능이 없기 때문에 브라우저 이쪽의 표현은 주로 서버 쪽을 통해 제어된다.다시 말하면 브라우저에서 누르는 버튼은 브라우저에서 직접 식별하지 않고 서버에 보낸 후 서버에서 메시지를 되돌려 처리한다는 것이다.
이런 사고방식을 사용하면 서버와 웹 페이지의 논리적 대비를 피할 수 있지만 사용자에게는 비교적 높은 지연을 느낄 수 있다.

서버


서버 측의 논리는 주로 메시지 전송과 사용자 신분 검증에 나타난다.
이 프로젝트는 사용자 신분에 대한 검증이 너무 강하지 않고 구분만 하면 된다.따라서 데이터베이스에서 사용자 데이터 저장을 할 필요가 없다. 사용자가 직면하는 것은 비밀번호가 필요 없는 로그인 인터페이스로 사용자 이름을 입력하는 것이다.물론 후기에 과정 센터 서버와 암호 검증을 하는 과정을 고려할 수 있다.
서버는 로그인 요청을 받은 후 사용자 이름과 다른 무작위 값을 결합하여md5를 이 사용자의 식별 코드로 계산하고 사용자 이름과 식별 코드를 클라이언트의 쿠키에 함께 존재합니다.사용자 이름은 사용자에게 표시되는 약한 식별 코드로 식별 코드는 사용자 이름에 무작위 수구md5를 추가하여 생성되고 충돌 확률이 비교적 적으며 서버 측의 사용자 신분의 직접 식별에 사용된다.
서버가 사용자의 WebSocket 요청을 받는 동시에 신분 식별 코드를 기록하고 페이지 접근 위치를 검사하여 형식에 따라 핸들을 대응하는 라즈베리 파이 집합에 추가합니다.사용자가 관련 키 메시지를 보내는 동시에 서버는 조종자를 판단하여 이 요청을 라즈베리 파이로 전송할지 여부를 결정합니다.
서버는 라즈베리 파이 메시지를 수신하는 동시에 모든 연결된 웹에 기본적으로 방송합니다.

라즈베리 파이


send(인간이 많음)send(병이 적음)send(부자)recv(인간이 많음)recv(소부)
라즈베리 파이는 socket을 통해 서버와 연결됩니다.서버 측에 Tornado 프레임워크가 이미 봉인되어 있기 때문에 사용하기가 비교적 쉽다.봉인되지 않은 라즈베리 파이 단자 socket 프로토콜은 여러 가지 이유로 캐시에 한 번이 아닌 요청이 존재하기 쉬우며, 모든 요청을 한꺼번에 읽은 후에 하나씩 처리해야 한다.그래서 발송과 수락할 때마다 두 번의 요청을 분리하는 구분 문자가 필요합니다.
정보 전송 형식인 json은 이런 기능을 가지고 있다. 왜냐하면 모든 합법적인 json의 끝은'}'이기 때문이다."}"을 식별하여 모든 요청을 분할하여 실행할 수 있습니다.
json 자체에} 문자열이 포함될 수 있지만, 현재 프로젝트의 수요에 따라 폭력적으로} 분할을 사용하면 됩니다.

파일 전송


웹소켓이 바이너리를 보내는 능력이 약하기 때문에 http 요청으로 서버로 파일을 보냅니다.파일을 보내는 동시에 브라우저는 쿠키에 있는 식별 코드가 조종자의 신분임을 검증하여 파일을 수신할지 여부를 판단합니다.
때문에bit 파일은 그리 크지 않기 때문에 파일을 받은 후 파일은 2진법으로 메모리에 존재하면 된다.
라즈베리 파이의 파일 획득 방식은 서버 v0.1 및 v0.2 버전에서 비교적 일치하지 않습니다.
서버 0.1 버전에서base64 인코딩 방식을 사용하여 바이너리를 문자열로 변환한 후 socket로 직접 발송합니다.라즈베리 파이 수신이 완료되면base64 디코딩을 사용하면 목표 파일을 얻을 수 있습니다.
서버 0.2 버전에서는 서버가 라즈베리 파이에 메시지를 보내고, 라즈베리 파이는 이 메시지의 내용에 따라 HTTP 프로토콜을 통해 서버의 파일을 다운로드합니다.

작은 매듭


이에 따라 브라우저 쪽과 라즈베리 파이의 교류는 이미 뚫렸고 파일의 전송도 관련 지원을 진행했으며 서버 쪽의 가장 주요한 부분은 이미 끝났다.
하지만 이 프로젝트는 보완이 필요하다.현재의 전단 페이지는 단지 사용할 수 있을 뿐, 후속적으로 증강되어야 한다. 예를 들어 인터럽트 재연결 지원, rtmp 생방송 재생 지원, 화면 버튼 디스플레이 지원 등이다.라즈베리 파이도 실험판과 통신을 해야만 진정으로 가치 있는 소식을 전달할 수 있다.
서버의 완성은 시작일 뿐입니다!

참고 자료

  • Python Socket 프로그래밍 - 채팅방 예시 프로그램
  • 45.Tornado, WebSocket 기반 채팅 서비스 구축
  • Tornado에서 파일의 업로드와 다운로드를 실현합니다
  • 좋은 웹페이지 즐겨찾기