머리말
HTTP 프로토콜은 인터넷에서 가장 중요한 프로토콜 중 하나로, 겉보기에는 단순해 보이지만 실제로는 자주 문제를 겪으며 우리는 여러 차례 이를 겪었습니다. 긴 연결과 패킷 파싱이 있습니다. HTTP 프로토콜에 대해 아무것도 알 수 없고, 철저히 이해해야 합니다. 그래서 저는 HTTP 프로토콜의 문제점과 경험을 공유하기 위해 이 시리즈를 썼습니다.
HTTP 프로토콜은 요청과 응답 패킷 모두에 헤더와 본체를 가지고 있으며, 본체는 HTML 페이지, jpeg 이미지와 같은 원하는 자원이며, 헤더는 특정 관습을 만드는 데 사용됩니다. 예를 들어, 클라이언트와 서버가 일부 전송 형식에 대해 합의하고, 클라이언트는 먼저 헤더를 받고, 어떤 형식 정보를 알게 된 후 본문을 읽기 시작합니다.
클라이언트: Accept-Encoding:gzip (저는 트래픽을 사용 중이니 먼저 다운로드하고 천천히 압축 해제)
서버 1: 콘텐츠인코딩: null (콘텐츠 인코딩 헤더 없음.) 압축은 제공하지 않아요, CPU가 무료가 아니니 원하시나요?
서버 2: Content-Encoding:gzip (트래픽 저장, 압축) 클라이언트: 연결: keep-alive (형님, 드디어 TCP 연결을 구축했으니 다음에 사용할 예정입니다)
서버 1: 연결: 유지(쉽지 않지만, 계속 사용)
서버 2: 연결: 종료 (계속 사용하는 분은 저희 TCP가 일회성 TCP이며, 다음에 다시 연결해야 합니다) HTTP 프로토콜에는 세 번의 핸드셰이크가 없으며, 클라이언트가 서버에 자원을 요청하면 서버 측이 우선합니다. 협상 프로세스가 없지만 서버가 클라이언트에게 직접 무엇을 해야 하는지 지시하는 헤더도 있습니다. 예를 들어, 위의 Content-Length는 서버가 클라이언트에게 본체 크기를 알려주는 것입니다. 하지만! 서버가 사전에 몸체의 크기를 정확히 알려주지 못할 수도 있습니다. 서버가 먼저 헤더를 작성하고, 그 다음에 본문을 작성해야 하며, 헤더에 본문 케이스를 쓰려면 사전에 본문 크기를 알아야 합니다. 본문이 동적으로 생성된다면, 서버가 완료한 후 헤더 쓰기를 시작하는데, 이는 많은 추가 오버헤드를 요구하므로 헤더에 콘텐츠 길이가 없을 수도 있습니다.
그렇다면 내담자는 어떻게 신체 크기를 알 수 있을까요? 서버는 세 가지 방식으로 알려줍니다.
1. 서버는 이미 리소스 크기를 알고 있으며 content-length 헤더를 통해 알려줍니다.
Content-Length:1076(body的大小是1076B,你读取1076B就可以完成任务了)
Transfer-Encoding: null
2. 서버는 자원의 크기를 미리 알 수 없거나, 자원 크기를 미리 계산하는 데 자원을 쓰기를 꺼려하므로, http 응답 메시지에 Transfer-Encoding:chunked라는 헤더를 추가합니다. 이는 블록 전송을 의미합니다. 각 블록은 고정된 형식을 사용하며, 앞에 블록 크기, 그 뒤에 데이터가 있고, 마지막 블록은 크기가 0입니다. 이렇게 클라이언트가 파싱할 때 쓸모없는 필드를 제거하는 데 신경을 써야 합니다.
Content-Length:null
Transfer-Encoding:chunked (接下来的body我要一块一块的传,每一块开始是这一块的大小,等我传到大小为0的块时,就没了)
3. 서버는 자원의 크기를 알지 못하며, 청크된 전송 모드를 지원하지 않아 content-length 헤더나 전송-인코딩 헤더가 없습니다. 이 시점에서 서버가 반환하는 헤더는 가까워야 합니다.
Content-Length:null
Transfer-Encoding:null
Connection:close(我不知道大小,我也用不了chunked,啥时候我关了tcp连接,就说明传输结束了)
|