我已经从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与此相关联,因为我认为没有任何开销是好的。 我不需要它。我还在main中完成了AfxSocketIback(),并从一个线程启动了另一个ListeningSocket。
netstat -a在ListeningSocket端口显示正确绑定,状态显示为Listening
// 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);
};
答案 0 :(得分: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 *传递给全局线程函数。将其强制转换为类指针并调用常规类方法。
答案 1 :(得分:2)
我也遇到了同样的问题 - 有人重新实现名为CAsyncSocketEx的CAsyncSocket - 构建为CAsyncSocket的功能替代。
就在这个星期,我以为我会看到我是否可以再次使用此代码,而且我遇到了同样的问题。由于async-window不是在具有消息循环的线程内创建的,因此事件不是从WSAAsyncSelect()...
触发的。