구현 | 서버제어

서버의 실행

select 함수를 실행한 뒤 각 서버의 run 함수를 호출하게 되는데, 서버의 run 함수는 자신이 연결되어 있는 커넥션들에 대해 입출력 작업을 최대 1회까지만 실행할 수 있습니다. select 함수의 결과로 read/write fd_set이 말하는 것은 1번 입출력이 가능한지에 대한 여부이기 때문입니다. 즉, 서버는 자신의 커넥션들에 대해 1번 순회하는 것이 1사이클입니다. 각 서버가 1사이클씩 돌면 manager 단에서 select 함수를 다시 실행하고, 또 서버들은 1사이클씩 도는 과정이 계속해서 반복되는 것입니다. 코드는 아래와 같습니다.

std::map<int, Connection>::iterator it = m_connections.begin();
while (it != m_connections.end())
{
	std::map<int, Connection>::iterator it2 = it++;
	int fd = it2->first;

	if (m_fd == fd)
		continue ;
		try {
			if (hasSendWork(it2->second))
			{
				runSend(it2->second);
				continue ;
			}
			if (hasExecuteWork(it2->second))
			{
				runExecute(it2->second);
				continue ;
			}
			if (hasRequest(it2->second)) {				
				runRecvAndSolve(it2->second);
			}
		} catch (Server::IOError& e) {
			ft::log(ServerManager::log_fd, ft::getTimestamp() + e.location() + std::string("\n"));
			closeConnection(fd);
		} catch (...) {
			ft::log(ServerManager::log_fd, ft::getTimestamp() + "detected some error" + std::string("\n"));
			closeConnection(fd);				
		}
}

이터레이터를 2개 사용하는 점을 눈여겨보세요. 이터레이터를 사용한 컨테이너 순회 중 인스턴스를 삭제하는 작업은 안전하지 않습니다.

읽고, 처리하고, 응답을 생성하고, 전송하는 것이 일반적인 흐름입니다. 하지만 왜 순서가 반대로 되어있을까요? 모든 입출력 작업은 select를 통해 안전성이 확인되어야 하고, 최대 1회까지 밖에 할 수 없기 때문입니다. 요청을 수신하고 처리한 뒤, 해당 클라이언트 소켓에 응답을 발송해도 되는지 확인하는 데 1사이클이 추가로 필요합니다.

runRecvAndSolve는 이름에서부터 2개 이상의 작업이 묶여있기 때문에 잘 고안된 함수는 아닙니다. Solve와 Execute의 차이가 직관적으로 구분되지 않는 것도 좋은 네이밍은 아닙니다.

커넥션 관리

같은 이유로 새로운 커넥션(클라이언트)을 추가하는 작업도 해당 서버의 커넥션 순회가 끝난 뒤에 처리합니다. 새롭게 연결한 클라이언트 소켓도 read fd_set에 등록되어 select 함수를 실행한 뒤 결과에 따라 요청을 읽어야 하기 때문에, 커넥션을 순회하기 전에 위치하면 처리 흐름이 직관적이지 않습니다. 한 번의 select 함수로 동시에 감시할 수 있는 소켓의 수는 1024개이고, 서버는 여러 개 생성될 수 있는 반면 디스크립터 테이블은 공유하기 때문에 현재 연결된 커넥션이 많은 경우에는 새로운 연결을 받지 않던가 한가한 커넥션을 끊고 연결해야 합니다.

if (hasNewConnection())
{
	if (m_connections.size() >= (1024 / m_manager->get_m_servers().size()))
	{
		int fd = getUnuseConnectionFd();
		if (fd == -1)
			return ;
		closeConnection(fd);
	}
	if (!acceptNewConnection())
		reportCreateNewConnectionLog();
}

Last updated