1

Winsock API を使用して C++ でサーバーを作成しています。実際に接続が来ている場合にのみaccept()関数を呼び出す可能性があるかどうか疑問に思っているので、accept()でスレッドをブロックする必要はありません。つまり、クライアントが接続しようとしている場合にのみ、スレッドを待機させて accept() 関数を呼び出したいと考えています。それは可能ですか?

4

1 に答える 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 に答える