Winsock API を使用して C++ でサーバーを作成しています。実際に接続が来ている場合にのみaccept()関数を呼び出す可能性があるかどうか疑問に思っているので、accept()でスレッドをブロックする必要はありません。つまり、クライアントが接続しようとしている場合にのみ、スレッドを待機させて accept() 関数を呼び出したいと考えています。それは可能ですか?
1533 次
1 に答える
0
Winsock を使用しているため、Microsoft 固有の拡張機能を使用できますAcceptEx
。これにより、受け入れを「オーバーラップ I/O」として実行できます。これは、概念的には、受け入れがバックグラウンドで実行されることを意味し、ときどきアクセスして、 をチェックするか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
}
誰かが私のコードの大きな明白なエラーを指摘するのを待ちます...
于 2013-06-12T11:28:12.797 に答える