Я создаю сервер на C ++ с помощью Winsock API. Мне интересно, есть ли возможность вызвать функцию accept () только в том случае, если какое-то соединение действительно идет, поэтому мне не нужно блокировать мой поток на accept (). Другими словами, я хотел бы, чтобы мой поток ждал и вызывал функцию accept () только тогда, когда клиент пытается подключиться. Это возможно?
Winsock - подождите с вызовом accept (), пока клиент действительно не попытается подключиться
Ответы (1)
Поскольку вы используете Winsock, вы можете использовать специфичную для Microsoft функцию расширения AcceptEx
. Это позволяет вам выполнять принятие как «перекрывающийся ввод-вывод», что концептуально означает, что принятие выполняется в фоновом режиме, и вы можете иногда заходить и проверять, произошло это или нет, либо проверив OverlappedResult
, либо выполнив Подождите на OverlappedHandle. AcceptEx
также дополнительно выполнит первый прием.
Без написания всего кода и его тщательного тестирования должно работать примерно следующее:
// The following:
// Has no error checking
// Assumes sListen is a bound listening socket
// Some other assumptions I've not listed :)
// Allocate space to store the two sockaddr's that AcceptEx will give you
//
char lpOutputBuffer[sizeof((sockaddr_in)+16) * 2];
SOCKET sAccept = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
WSAOVERLAPPED olOverlap;
ZeroMemory(&olOverlap, sizeof(WSAOVERLAPPED));
olOverlap.hEvent = WSACreateEvent();
DWORD dwBytes;
BOOL bAcceptRet =
AcceptEx(sListen, // the listen socket
sAccept, // the socket to use for the accepted connection
lpOutputBuffer, // where to store the received information
0, // don't do a receive, just store the local and remote addresses
sizeof((sockaddr_in)+16), // size of the local address area
sizeof((sockaddr_in)+16), // size of the remote address area
&dwBytes, // set to received bytes if we complete synchronously
&olOverlap); // our overlapped structure
if (bAcceptRet) {
// the function completed synchronously.
// lpOutputBuffer should contain the address information.
// sAccept should be a connected socket
} else {
// the function didn't complete synchronously, so is the accept Pending?
if (ERROR_IO_PENDING == WSAGetLastError()) {
// in this case, our Accept hasn't happened yet...
// later in our code we can do the following to check if an accept has occurred:
// note that the FALSE tells WSAGetOverlappedResult not to wait for the I/O to complete
// it should return immediately
...
DWORD dwFlags;
if (WSAGetOverlappedResult(sListen, &olOverlap, &dwBytes, FALSE, &dwFlags)) {
// the accept has succeeded, so do whatever we need to do with sAccept.
}
...
}
}
Конечно, это очень быстрый, скомпилированный фрагмент, вероятно, неработающего, не компилируемого кода, но он должен дать вам представление о том, как вы могли бы сделать что-то похожее на то, что вы хотите, и где искать.
Между прочим, технически нет необходимости устанавливать параметр hEvent
структуры WSAOVERLAPPED
, но это позволяет вам фактически дождаться завершения запроса:
if (WAIT_OBJECT_0 == WaitForSingleObject(olOverlap.hEvent, INFINITE)) {
// The accept occurred, so do something with it
}
Теперь я подожду, пока кто-нибудь укажет на огромные вопиющие ошибки в моем коде ...
WSAAsyncEvent()
илиWSAAsyncSelect()
, чтобы Winsock уведомлял вас о новом подключении. - person Remy Lebeau   schedule 08.06.2013