2012-08-15 73 views
0

我从CAsyncSocket类实现我的ClientSocket的类:CAsyncSocket不发射事件?

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继承了大众的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 brakepoints,它永远不会到来这里ListeningSocket的端口和状态绑定。

编辑:

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); 
    }; 
+0

我是新来的太Winsocks。 – 2012-08-15 18:59:53

+0

“bind()”和“listen()”的调用在哪里? – 2012-08-15 19:21:28

+0

@Nikolai我编辑过的问题包括Create()和Listen()。请看一看。 – 2012-08-16 04:03:06

回答

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需要全局函数作为参数(或类静态函数)。要调用常规类方法,请使用“this”作为CreateThread参数,该参数作为void *传递给全局线程函数。将其重新转换为类指针并调用常规的类方法。

+0

非常感谢。该函数对于CreateThread()的参数必须是静态的。顺便说一句我现在面临着StackOverflowException。 – 2012-08-16 07:32:34

+0

答案已编辑。 – 2012-08-16 07:48:38

+0

我想通了:)从析构函数中删除这个。我有性能问题。有小费吗 ? – 2012-08-16 07:48:53

2

我也遇到过同样的问题 - 有人重新实现CAsyncSocket,名为CAsyncSocketEx - 构建为CAsyncSocket的函数替换。

就在本周,我想我会看看我是否可以再次使用此代码,并且遇到了同样的问题。由于具有消息循环的线程中没有创建异步窗口,该事件不会从WSAAsyncSelect()射击...

看到这一点:http://support.microsoft.com/kb/90975