2014-06-16 2 views
1

Windows 및 Unix 시스템 모두에서 C++로 서버를 작성하고 있습니다.push() 서버에서 select() 문제가 발생했습니다.

이 서버의 핵심 기능은 언제든지 네트워크 패킷을 수신하고 보낼 수 있어야한다는 것입니다. 특히, 서버는 메시지에 대한 응답으로 클라이언트에 데이터를 보낼 수 있어야하며 밀어 넣기시 비동기식으로 패킷을 보낼 수 있어야합니다.

위에서 설명한 시나리오에서 select() 함수를 사용하는 솔루션을 구현하는 데 어려움이 있습니다. 현재 구현 한 솔루션이 나를 전혀 설득하지 못해 더 나은 패턴/솔루션으로 구현할 수 있다고 생각합니다.

현재 서버 소켓 (새 연결 수락) 및 서버에 연결된 소켓에 대한 이벤트를 수신하여 선택을 수행하는 전용 스레드 (선택기)가 있습니다.

이 주요 선택() 루프 :

if((sel_res_ = select(nfds_+1, &read_FDs_, NULL, &excep_FDs_, &sel_timeout)) > 0){ 
    if(FD_ISSET(serv_socket, &read_FDs_)){ 
     //we have to handle a newly connection. 
     ... 
     if(sel_res_ > 1){ 
      //in addition to the newly connection, there is also some other message incoming on client sockets. 
      ... 
     } 
    }else{ 
     //we have to handle incoming messages on client sockets 
     ... 
    } 
} 

이 솔루션은 데이터를 수신 잘 작동 및 동기 형태로 클라이언트 요청에 응답 할 수 있습니다. 그러나 서버는 비동기 데이터를 보내고 필요한 경우 패킷을 밀어 넣을 수 있어야합니다.

이렇게하려면 현재 클라이언트 소켓에서 send()을 직접 수행하는 별도의 스레드를 사용합니다.

이 솔루션은 나를 설득하지 않으며 선택기 스레드에서 수신 및 전송하는 패킷을 중앙 집중화하려고합니다.

주요한 어려움은 성격 상으로는 select()이 차단되어 클라이언트가 패킷을 보내지 않거나 시간 제한이 트리거 될 때까지 제어 할 수 없다는 것입니다. 제한 시간을 매우 낮게 설정하는 해결책은 나를 설득하지 못합니다. 나는 실제로 액티브 대기를하고있는 쉬운 솔루션이라고 생각한다. 그러나 푸쉬 패킷을 보내기 전에 타임 아웃 가격을 지불 할 최악의 경우는 아니다.

나는 더 우아한 해결책이라고 생각했다. 내 생각에, 잘 작동하지만 Unix/Linux 플랫폼에서만 가능합니다. 익명 파이프를 사용하여 익명 파이프 읽기 디스크립터 select()에 삽입하려고 생각했습니다. 스레드가 푸시에서 데이터를 보내려고하면이 파이프에 무엇인가를 씁니다. select()을 중단하고 시간을 크게 낭비하지 않고 데이터를 클라이언트에 보낼 수있는 선택기로 제어를 반환합니다. 이 시스템의 select() 기능이 실제로 소켓 인 fds에서만 작동하기 때문에 불행히도 Windows에서이 솔루션을 구현할 수 없다고 생각합니다.

그래서 질문입니다. 이런 종류의 시나리오 (Linux와 Windows 모두)를 해결하는 데 사용할 수있는 잘 알려진 해결책이 있습니까?

+0

두 개의 스레드를 사용합니다. 하나는 읽기 용이고 다른 하나는 쓰기 용입니다. – alk

답변

1

자체 연결 UDP 소켓을 만들 수 있습니다. 이것은 Windows와 Linux에서 동일하게 작동합니다.

기본적으로, 당신은 INADDR_LOOPBACK 및 포트 0과 connect() 그 자체 (getsockname()에서 가져온 주소)에 bind()에게 그것을 UDP 소켓을 만듭니다.

이 시점에서 자신을 깨우기 위해 1 바이트 메시지 (또는 좀 더 구체적인 메시지)를 보낼 수 있습니다.

+0

좋은 솔루션입니다. 감사합니다. – Giuseppe

관련 문제