🍭
webserv
  • Webserv tutorials
  • 학습 | 웹(Web)
  • 학습 | 웹서버(Webserver)
  • 학습 | HTTP 개요
  • 학습 | 리퀘스트(Request)
  • 학습 | 리스펀스(Response)
  • 학습 | CGI
  • 학습 | RFC
  • 학습 | 소켓과 TCP 커넥션
  • 학습 | 서브젝트(Mandatory)
  • 실습 | 서버 프로그램
  • 실습 | 클라이언트 프로그램
  • 실습 | 통신 테스트
  • 실습 | telnet
  • 실습 | nginx
  • 설계 | 설계의 중요성
  • 설계 | 플로우차트
  • 설계 | 설정 파일
  • 설계 | 객체 설계
  • 설계 | 팀 코드 컨벤션
  • 설계 | 클래스 명세서
  • 설계 | 협업환경 구성
  • 구현 | 메인함수
  • 구현 | 서버생성
  • 구현 | Select
  • 구현 | 서버제어
  • 구현 | 요청 읽기
  • 구현 | 메소드 실행하기
  • 구현 | 응답 생성하기
  • 구현 | CGI 실행하기
  • 구현 | 응답 보내기
  • 구현 | 주요 메소드
  • 구현 | Libft
  • 구현 | 구현 테크닉 16
  • 구현 | 로그
  • 테스트 | Postman
  • 테스트 | Tester
  • 테스트 | 브라우저
  • 테스트 | Siege
  • 보너스 파트
  • 학습 레퍼런스
  • 튜토리얼을 끝내며
Powered by GitBook
On this page
  • Response 객체의 응답 메시지화
  • 응답 전송하기

Was this helpful?

구현 | 응답 보내기

Response 객체의 응답 메시지화

응답을 보낼 때 가장 먼저 해야 할 작업은 Response 객체의 멤버 변수들을 응답 메시지 문자열로 변환하는 것입니다. 코드는 아래와 같습니다.

std::string
Response::getString() const
{	
	std::string message;
	std::map<std::string, std::string>::const_iterator it = this->m_headers.begin();

	message = m_protocol + " " + ft::to_string(m_status_code) + " " + m_status_description + "\r\n";
	for (; it != this->m_headers.end(); ++it)
		message += it->first + ": " + it->second + "\r\n";
	if (m_connection_type == CLOSE || m_status_code < 200 || m_status_code > 299)
		message += "Connection: close\r\n";
	else
		message += "Connection: Keep-Alive\r\n";
	if (m_transfer_type == CHUNKED) {
		message += "Transfer-Encoding: chunked\r\n\r\n";
		int size = this->m_content.size();
		int count;
		std::string data = m_content;
		int added = 0;
		while (size > 0)
		{
			if (size > BUFFER_SIZE)
				count = BUFFER_SIZE;
			else
				count = size;
			message += ft::itos(ft::to_string(count), 10, 16) + "\r\n";
			message += data.substr(added, count) + "\r\n";
			size -= count;
			added += count;
		}
		data.clear();
		message += "0\r\n\r\n";
	}
	else
	{
		message += "\r\n";
		message += this->m_content;
	}
	return (message);
}

프로토콜과 상태 코드, 사유 구절을 합쳐 시작 줄을 만듭니다. 헤더 맵의 key와 value들을 쌍으로 헤더를 추가합니다. body의 경우 chunked encoding인 경우 BUFFER_SIZE보다 크지 않도록 잘라서 16진수 토큰과 함께 넣습니다. 이런 과정들을 거쳐 메시지를 만들고, 커넥션 객체의 write 버 변수에 저장합니다.

응답 전송하기

응답을 전송하는 과정은 단순합니다. write 버프에 저장된 응답 메시지를 client socket fd를 이용하여 전송하는 것이죠. 다만 보내야 할 메시지의 길이가 큰 경우에는 여러 차례에 걸쳐 나눠서 보내야 합니다. 코드는 아래와 같습니다.

bool
Connection::sendFromWbuf(int fd)
{
	int count = m_wbuf_data_size - m_send_data_size;
	if (count > BUFFER_SIZE)
		count = BUFFER_SIZE;
	count = send(fd, m_wbuf.c_str() + m_send_data_size, count, 0);
	if (count == 0 || count == -1) 
		throw (Server::IOError((("IO error detected to send response message to client ") + ft::to_string(fd)).c_str()));
	m_send_data_size += count;
	return (true);
}

send든 write든 write operation 작업이 0이나 -1을 리턴하는 경우 Connection(Client)을 제거해야 합니다.

Previous구현 | CGI 실행하기Next구현 | 주요 메소드

Last updated 4 years ago

Was this helpful?