다음과 같은 방법으로 버클리 소켓 선택 기능을 사용하고 있습니다.버클리 소켓에서 스레드 알림 사용
/*Windows and linux typedefs/aliases/includes are made here with wsa
junk already taken care of.*/
/**Check if a socket can receive data without waiting.
\param socket The os level socket to check.
\param to The timeout value. A nullptr value will block forever, and zero
for each member of the value will cause it to return immediately.
\return True if recv can be called on the socket without blocking.*/
bool CanReceive(OSSocket& socket,
const timeval * to)
{
fd_set set = {};
FD_SET(socket, &set);
timeval* toCopy = nullptr;
if (to)
{
toCopy = new timeval;
*toCopy = *to;
}
int error = select((int)socket, &set, 0, 0, toCopy);
delete toCopy;
if (error == -1)
throw Err(); //will auto set from errno.
else if (error == 0)
return false;
else
return true;
}
나는 (aother 클래스에 싸서) 소켓의 컨테이너를보고 소켓에 액세스 할 준비가 무엇인지에 대한 정보를 저장하는 별도의 용기에 ID를 추가하는 클래스를 작성했습니다. 지도는 unordered_map입니다.
while(m_running)
{
for(auto& e : m_idMap)
{
auto id = e.first;
auto socket = e.second;
timeval timeout = ZeroTime; /*0sec, 0micro*/
if(CanReceive(socket,&timeout) &&
std::count(m_readyList.begin(),m_readyList.end(),socket) == 0)
{
/*only add sockets that are not on the list already.*/
m_readyList.push_back(id);
}
}
}
내가 발견했는지 많은거야,이 코드는 미친 듯이 빠른 실행과 내일 (지도에서 하나의 소켓 40 %의 CPU 사용량)가없는 것처럼 CPU를 먹는다. 내 첫 번째 솔루션은 초당 반복을 설정된 값으로 유지하는 스마트 대기 함수를 사용하는 것이 었습니다. 그것은 어떤 사람들에게는 괜찮은 것처럼 보였다. 내 질문은 :이 방법을 사용하지 않고 소켓 준비가되었을 때 어떻게 알림을받을 수 있습니까? 비록 그것이 휴대 할 수 있도록 매크로 쓰레기가 필요할지라도 괜찮습니다. 운영 체제에서 나를 감시하고 소켓 준비가되었을 때 알림이나 이벤트를받을 수있는 방법이있을 수 있다고 생각할 수 있습니다. 그냥 분명히하기 위해, 나는 닷넷을 사용하지 않기로했다.
루프가 자체 스레드에서 실행되고 소켓 준비가 완료되면 소프트웨어의 다른 부분에 알림이 전송됩니다. 전체가 멀티 스레드이며이 부분을 제외한 모든 부분에서 이벤트 기반 알림 시스템을 사용하여 대기중인 대기 문제를 제거합니다. 나는이 것들이 OS에 의존하고이 영역에서 제한된다는 것을 이해한다.
편집 : 소켓은 BLOCKING 모드로 실행되지만 select에는 시간 제한이 없으므로 차단되지 않습니다. 그러나 전용 스레드에서 작동됩니다. 편집 : 시스템의 스마트 절전 기능이 뛰어나지 만 일부 알림 시스템 (예 : OS)에서 가능한만큼 좋은 성능을 발휘하지 못합니다.
'recv'를 호출하지 않는 이유는 무엇입니까? 'recv'가 무엇을 할 것인지를 예측하기 위해'select'를 호출해야하는 이유는 무엇입니까? 그냥'recv'를 호출하고 무슨 일이 일어나는지 보지 않으시겠습니까? –
또한이 작업을 수행하려면 실제로 라이브러리를 사용해야합니다. 100 % 제대로하는 것은 일의 * 많은 *이며, 발견 한 것처럼 최소한의 코드로 위조하는 것은 고통 스럽습니다. ASIO에는 강력한 기능이 있습니다. –
David Schwartz : 소켓에 즉시 제공 할 항목이없는 경우 다른 소켓으로 이동하여 나에게 뭔가가 있는지 확인합니다. 수천 개의 소켓이 있습니다. recv를 호출하여 하나의 소켓을 차단하면 현재 준비가되어있는 다른 소켓은 무시됩니다. no-block 옵션을 사용하여 recv를 호출해도 대기 중으로 계속 바쁠 것이므로 아무 것도 해결하지 못합니다. – Matt