2016-08-12 38 views
9

クライアントプロセスがTCP MyCAsyncSocket::Connectをサーバープロセスに実行するMFC C++アプリケーションを作成しました。サーバプロセスは、MyCAsyncSocket::OnAcceptで応答します。Detachは、指定されたソケットを返します。Attachソケットを作成し、送信するデータを読み取ります。 MSDNはDetachの後にm_hSocketをNULLに設定するように規定しています。サーバーがありませんクライアントを実行中のOnAccept通知

正常に動作しますが、1回だけです。クライアントが同じソケットアドレスにConnectをもう一度試行すると、OnAccept通知は発生しません。ここでは、サーバーのコードは次のとおりです。

void MyCAsyncSocket::OnAccept(int nErrorCode) 
{ 
    BOOL socketResult = FALSE; 

    CAsyncSocket syncSocket; 

    Accept(syncSocket); 
    AsyncSelect(FD_READ | FD_CLOSE); 

    SOCKET socket = syncSocket.Detach(); 
    m_hSocket = NULL; // prescribed by msdn 

    ... // go attach the socket in a worker thread, read the socket and do work 

    // try to re-establish listener. 
    ...Create(// error: attempt 2: ASSERT(m_hSocket == INVALID_SOCKET) 
    endPoint.portNumber, // ok: same as client port number 
    SOCK_STREAM, 
    FD_READ | FD_WRITE | FD_ACCEPT | FD_CONNECT | FD_CLOSE, 
    endPoint.ipAddress // ok: same as client ip address 
); 

    ...Listen(); // error: attempt 1: no error case, but still doesn't work 


    CAsyncSocket::OnAccept(nErrorCode); 
} 

試み1:OnAcceptDetach後、私はListenと、次の試してみましたが、私は、これはエラーを聞く取得:「WSAENOTSOCK:記述子がソケットではありません」。これが何を意味するかわからない。

試み2:私は、その後のフォローアップListenCreateを実行しようとしたが、これはアサートを引き起こした:として定義されるASSERT(m_hSocket == INVALID_SOCKET);:私は単にリスナーソケットを破壊プロトタイプコードで

/* 
* This is used instead of -1, since the 
* SOCKET type is unsigned. 
*/ 
#define INVALID_SOCKET (SOCKET)(~0) 

とそれを最初から再作成しましたが、実動コードの場合、これは受け入れられません。なぜなら、ソケットスレッドのリスニング機能がマイクロ秒以上中断されないことを保証するためです。

Connectイオンのためにソケットを準備するために、適切なセマンティクスがどのようなものであるべきかを知っていますか?

答えて

2

ソケットでAsyncSelect(FD_READ | FD_CLOSE)を呼び出すと、実際には新しく受け入れられたソケット(syncSocket)で呼び出すと思うと思います。

AsyncSelect(FD_READ | FD_CLOSE)を呼び出すと、リスニングソケットのFD_ACCEPT通知がクリアされ、リスニングソケットに将来の接続が確立されたときにOnAcceptが呼び出されないことが保証されます。

さらに、上記のm_hSocket = NULLを設定すると、ソケットのリスニングソケットのハンドルをNULLにしています。新しく受け入れられたソケット(syncSocket)のソケットではありません。

さらに、MSDNが正しく(https://msdn.microsoft.com/en-us/library/05sz8hz8.aspx)、Detach()メソッド自体が関連するハンドルをNULLにしていて、これを自分で行う必要はありません。 [も、私は期待して、あなたのことができます - m_hSocketがsyncSocketのプライベートメンバであるべき以来]

私はあなたのOnAcceptのコードはもっとように見えることを期待する:

void MyCAsyncSocket::OnAccept(int nErrorCode) 
{ 
    BOOL socketResult = FALSE; 

    CAsyncSocket syncSocket; 

    Accept(syncSocket); 

    SOCKET socket = syncSocket.Detach(); 

    ... // go attach the socket in a worker thread, which reads the socket and does work 

} 
+0

が動作するようになりました。 'AsyncSelect(FD_READ | FD_CLOSE);と' m_hSocket = NULL; 'ステートメントの両方を削除し、2番目の' OnAccept'通知が届きました。もちろん、AsyncSelect(FD_ACCEPT | FD_READ | FD_CLOSE);も機能します。ナイスキャッチ。 – rtischer8277

関連する問題