0

CAsyncSocketからClientSocketクラスを実装しました。

class ClientSocket : public CAsyncSocket
{
    // this socket sends data back to "backSocket" which points to this only for 
    // testing but it can send data to other sockets like that too.
ClientSocket * backSocket;

    // store some data in backupData untill connection is established.
    StringBuilder * backupData;

public:

virtual void OnClose(int);
virtual void OnReceive(int);
ClientSocket(void);
bool ConnectToBACK();
virtual ~ClientSocket(void);
};

ClientSocket::ClientSocket(void)
{
// DONOT run to back !!! recursive calls otherwise.
backSocket = NULL;
backupData = NULL;
}

bool ClientSocket::ConnectToBACK()
{
if(this->backSocket != NULL)
    return true;

// just for debugging :)
this->backSocket = this;
return true;
}

ClientSocket::~ClientSocket(void)
{
this->Close();
if(this->backSocket)
{
    this->backSocket->Close();
    delete this->backSocket;
    this->backSocket = NULL;
}
}

void ClientSocket::OnClose(int nErrorCode)
{
if(this->backSocket != NULL)
{
    this->backSocket->Close();
}

CAsyncSocket::OnClose(nErrorCode);
}

void ClientSocket::OnReceive(int nErrorCode)
{
if(nErrorCode == 0)
{
    char *buffer = new char[2049];
    int bufLen = sizeof(buffer)/sizeof(buffer[0]);

    int received = this->Receive(buffer, bufLen-1, 0);
    if(received == SOCKET_ERROR)
    {
        return ;
    }

    if(this->ConnectToback())
    {
        if(backupData)
        {
            int backupLen;
            char *backup = backupData->ToString(&backupLen);
            this->backSocket->Send(backup, backupLen);
            delete backupData;
            delete [] backup;
            backupData = NULL;
        }

        this->backSocket->Send(buffer, received);
        delete buffer;
    }
    else
    {
        if(backupData == NULL)
        {
            backupData = new StringBuilder();
        }
        backupData->Insert(buffer, received);
    }
}

CAsyncSocket::OnReceive(nErrorCode);
 }

オーバーヘッドがないので良いと思ったので、これにGUIを関連付けていません。私はそれを必要としません。また、メインでAfxSocketIback()を実行し、スレッドから別のListeningSocketを開始しました。

netstat -aは、ListeningSocketのポートでの適切なバインディングと、リスニングとしてのステータスを示します。

//ListeningSocketはパブリックCAsyncSocketを継承します

 void ListeningSocket::OnAccept(int nErrorCode)
 {
 #ifdef DEBUG
std::cout << "\nOnAccepting Proxy Server :)";
 #endif
if(nErrorCode == 0)
{
    ClientSocket *FromCliet = new ClientSocket();
    FromCliet->value = 100;
    if(this->Accept(*FromCliet, NULL, NULL))
    {
                    // Connection just has ClientSocket * client
        Connection * connection = new Connection(FromCliet);
        // a list<Connection *> is stored in ListeningSocket
                    this->clients.push_front(connection);
    }
    else
    {
        std::cerr << "\nFailed to accept connection from Client";
    }
}

CAsyncSocket::OnAccept(nErrorCode);
 }

ListenSocket :: OnAcceptにブレーキポイントを設定すると、ここに来ることはありません。

編集:

 static DWORD WINAPI StartListening(LPVOID param)
 {
       ListeningSocket *app = (ListeningSocket *)param;
   if(false == app->Create(7897, SOCK_STREAM, 31, "127.0.0.1"))
   {
     std::cerr << "\nCould not create\bind to port";
     delete app;
     return -1;
   }
   if(false == app->Listen())
   {
          std::cerr << "\nCould not listen";
      app->Close();
      delete app;
      return -1;
   }
   return 0;
 }

 int ListeningSocket::Start()
 {
      if(NULL == CreateThread(NULL,0, StartListening, (LPVOID)this,0, NULL))
   {
    return -1;
   }

  return 0;
 }

私はMFCウィザードソリューションのようにそれを作りませんでした。単純なプロジェクトとmain()があります。

 My ListeningSocket Class is Singletone Class:  
 class ListeningSocket : public CAsyncSocket
 {

    private:
static ListeningSocket * ListeningSocket;
std::list<Connection *> clients;
ListeningSocket(void);

    public:
// overrides
virtual void OnAccept(int);
virtual void OnClose(int);
static ListeningSocket * GetListeningSocket();
virtual ~ListeningSocket(void);
virtual void Close();
int Start(void);
    };
4

2 に答える 2

2

CAsyncSocketクラスは、イベントを発生させるためにWindowsメッセージを内部的に使用します。メッセージループのあるスレッドでCAsyncSocketから派生したクラスを作成する必要があります。この場合、イベントが呼び出されます。擬似コード:

// This function runs in the context of worker thread
void MyClass::ThreadFunction()
{
    mySocket.Create(...);    // creating CAsyncSocket-derived class

    // Run message loop.
    BOOL bRes = FALSE;
    MSG msg;

    while((bRes = GetMessage( &msg, NULL, 0, 0 )) != 0)
    { 
        if (bRes == -1)
        {
            break;
        }
        else
        {
            TranslateMessage(&msg); 
            DispatchMessage(&msg); 
        }
    }
}

このスレッドを停止するには、PostQuitMessage関数を使用します。

編集します。あなたがそれらに精通していることを前提として、私はすべてのマルチスレッドの詳細を投稿しませんでした。通常、CreateThreadには、パラメーターとしてグローバル関数(またはクラス静的関数)が必要です。通常のクラスメソッドを呼び出すには、CreateThreadパラメータとして「this」を使用します。これはvoid*としてグローバルスレッド関数に渡されます。それをクラスポインタにキャストして戻し、通常のクラスメソッドを呼び出します。

于 2012-08-16T06:33:38.813 に答える
2

また、CAsyncSocketの関数置換として構築されたCAsyncSocketExと呼ばれるCAsyncSocketの誰かの再実装で、これと同じ問題が発生しました。

ちょうど今週、このコードをもう一度使用できるかどうかを確認したいと思いましたが、これとまったく同じ問題が発生しました。メッセージループのあるスレッド内に非同期ウィンドウが作成されなかったため、WSAAsyncSelect()からイベントが発生していませんでした...

これを参照してください:http ://support.microsoft.com/kb/90975

于 2013-01-31T01:39:37.917 に答える