>  기사  >  웹 프론트엔드  >  NODEJS의 http 구현에 대한 자세한 소개

NODEJS의 http 구현에 대한 자세한 소개

亚连
亚连원래의
2018-06-13 17:31:291942검색

이 글은 주로 NODEJS의 http 구현에 대한 기술적인 과정과 상세한 분석을 소개합니다. 필요한 친구들은 참고할 수 있습니다.

1. 소개

현재 HTTP 프로토콜은 인터넷에서 가장 널리 사용되는 네트워크 프로토콜이자 프런트엔드 ER이 가장 많이 접촉하는 프로토콜이기도 합니다. nodejs에서 http 모듈의 구현을 읽으면 HTTP 프로토콜에 대해 더 깊이 이해할 수 있습니다. HTTP 프로토콜은 TCP 프로토콜을 기반으로 하는 애플리케이션 계층 프로토콜이며, 그 구현은 TCP/IP 프로토콜 계열과 분리될 수 없습니다. 코드 구현의 경우 http 모듈은 net 모듈에 따라 다릅니다.

아래 그림과 같이 nodejs에서 http는 net 모듈을 통해 데이터를 전송하고, 데이터를 얻은 후 HTTP_PARSER를 사용하여 데이터를 구문 분석합니다.

2. 소스 코드

HTTP 서비스 시작

nodejs에서 HTTP 서비스를 시작하는 것은 매우 간단합니다. 서버 객체를 인스턴스화하고 특정 포트를 수신하기만 하면 됩니다:

const Server = require('./libs/http').Server
const server = new Server( function(req, res) { 
 res.writeHead(200)
 res.end('hello world')
})
server.listen(9999)

SERVER 클래스

서버 클래스 net.Server를 상속하고 'connection' 이벤트를 수신합니다.

Server 클래스에서는 두 가지 주요 작업이 수행됩니다. 1. NET 모듈 초기화 및 TCP 네트워크 모니터링 설정 2. 자체 요청 이벤트 모니터링

클라이언트 요청이 오면 Server 인스턴스는 먼저 '연결'을 수신합니다. 이벤트를 통해 TCP 연결을 설정하고 ConnectionListener에 소켓 개체를 노출합니다. 다음으로, HTTP 모듈은 소켓 개체를 통해 클라이언트와 상호 작용합니다.

요청이 도착하면 서버는 자체 요청 이벤트를 트리거하고 서버 인스턴스를 생성할 때 전달된 콜백 함수인 requestListener 메서드를 호출합니다.

new Server( function(req, res) { 
 res.writeHead(200)
 res.end('hello world')
})

참고: 소켓 개체는 클라이언트와 데이터를 교환할 수 있는 TCP 프로토콜의 구현과 유사합니다. 참고: ConnectionListener 함수에서 구문 분석기 인스턴스도 초기화되고 onIncoming 함수 HTTP 구문 분석기가 바인딩됩니다.
전체 구문 분석 프로세스는 ConnectionListener에서 수행됩니다. 소켓은 'data' 이벤트를 통해 TCP가 푸시한 데이터를 얻습니다. 즉, parser.excute()라는 데이터를 먼저 구문 분석합니다. 파싱 ​​도구는 파서(parser)입니다. 파서의 재사용을 달성하기 위해 저자는 'FreeList 풀'에서 파서를 얻었음을 언급할 가치가 있습니다.

...
const parser = parsers.alloc() 
...
connectionListener(socket) { 
  socket.on('data', socketOnData)

  // TCP推入数据,parser进行解析
  function socketOnData(d) {
    ...
    const ret = parser.execute(d)
    ...
  }
}

1. TCP 데이터가 도착하면 먼저 Execute()

2. 단서를 따라가서 우리는 parser.excute가 Excute(node_http_parser.cc)라는 것을 알았습니다. Excute는 아웃소싱일 뿐이며 구체적인 작업은 http_parser_excute(http_parser.c)에서 수행됩니다.

node_http_parser.cc는 http_parser.c의 래퍼일 뿐입니다. http_parser.c는 데이터를 위해 node_http_parser.cc와 상호 작용하기 위해 외부에 노출된 7개의 콜백 주기 함수를 사용합니다.

3. http_parser.c에는 HTTP_CB와 HTTP_DATA_CB의 두 가지 유형의 콜백만 있습니다. 오버로딩을 통해 아래와 같이 두 가지 유형의 함수에 8개의 주기 함수가 등록됩니다.

4. http_parser에는 8개의 등록된 콜백 함수가 있지만 node_http_parser.cc는 4개의 주기 함수만 외부에 노출합니다.

parserOnHeaders

parserOnHeadersComplete

parserOnBody

parserOnMessageComplete

5. http_parser.c가 on_headers_complete로 구문 분석되면 그림과 같이 HTTP_CB(on_headers_complete) 콜백 함수를 실행합니다.

kOnHeadersComplete 콜백 함수가 실행됩니다. js)

6. 이제 요청 헤더 구문 분석이 기본적으로 완료됩니다. 다음으로 IncomingMessage의 인스턴스를 생성한 후 요청 헤더 데이터를 인스턴스에 패키징합니다.

onIncoming 콜백 함수를 실행하고 획득한 IncomingMessage 인스턴스를 매개변수로 전달합니다.

function parserOnHeadersComplete (versionMajor, versionMinor, headers, method, url, statusCode, statusMessage, upgrade, shouldKeepAlive) { 
  ...
  parser.incoming = new IncomingMessage(parser.socket)
  parser.incoming.httpVersionMajor = versionMajor
  parser.incoming.httpVersionMinor = versionMinor
  parser.incoming.httpVersion = versionMajor + '.' + versionMinor
  parser.incoming.url = url
  ...
  skipBody = parser.onIncoming(parser.incoming, shouldKeepAlive)

}

7.parserOnIncoming에서 ServerResponse 인스턴스를 만듭니다.

req와 res의 두 인스턴스를 사용하면 서버에서 모니터링하는 요청 이벤트가 트리거됩니다.

서버가 인스턴스화되면 requestListener가 요청 이벤트를 모니터링하는 함수 매개변수로 사용됩니다.

8. 서버가 생성되었을 때로 돌아갑니다.

const server = new Server( function(req, res) { 
  var data = ''
  req.on('data', function(chunk){
    console.log('chunk: ' + chunk)
    data += chunk;
  })
  res.writeHead(200)
  res.end('hello world')
})

요약하면 http_parser가 헤더를 구문 분석한 후 요청 이벤트가 트리거됩니다.

본문 데이터를 어디에 넣을 것인가? 실제로 본체 데이터는 사용자가 데이터 이벤트를 사용하여 데이터를 수신할 때까지 스트림에 배치됩니다. 즉, 요청이 트리거되면 본문이 구문 분석되지 않습니다.

3. 프로세스 개요 전체 http 요청은 다음과 같습니다. - 클라이언트는 HTTP 요청을 시작하고 먼저 서버 측에서 연결 이벤트를 트리거한 후 TCP 링크를 설정합니다.

연결 이벤트를 수신한 후 서버는 TCP 연결을 설정하고 소켓을 노출하며 소켓을 통해 '데이터' 이벤트를 수신합니다. http-parser를 초기화하여 후속 데이터 구문 분석을 준비합니다.

HTTP 요청 데이터가 서버에 도달하고, 파서는 실행 메소드를 실행하여 파싱합니다. 요청 헤더가 성공적으로 파싱되면 콜백을 통해 요청 이벤트가 트리거됩니다.

이 시점에서 서버 콜백 함수에서 이 http 요청에 대한 요청을 받았습니다

4. 결론

nodejs의 기본 라이브러리 중 다수가 C++/C로 작성되었기 때문에 읽기 및 디버깅 과정에서 매우 불편합니다. 제가 직접 소스코드를 읽을 때는 소스코드 중 JS 부분에만 집중했습니다. 예를 들어 TCP의 3방향 핸드셰이크와 4방향 웨이브는 구현 세부 사항을 자세히 다루지 않습니다. 위 분석에는 http-body 분석이 포함되지 않습니다. 본문이 있는 네트워크 요청의 경우 실제 상황은 더 복잡하며 일부 세부 사항은 완전히 이해되지 않습니다. 다음에 요약해서 공유할 때 부족한 부분은 모두 채워나갈 수 있도록 최선을 다하겠습니다.

위 내용은 모두를 위해 제가 정리한 내용입니다. 앞으로 모든 사람에게 도움이 되기를 바랍니다.

관련 기사:

JS를 사용하여 노드 요소를 가져오는 방법

NodeJS를 사용하여 WebSocket 기능을 구현하는 방법

Express에서 log4js의 실제 사용에 대해

위 내용은 NODEJS의 http 구현에 대한 자세한 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.