异步winsock服务器包装器,CPU滞后 - C++
我正在尝试编写一个服务器应用程序包装器,就像我对任何应用程序所做的那样,我已经搜索了一个多星期的关于异步套接字的至少像样的指南或教程(这个包装器必须是异步的),到目前为止我能做什么这样做是这样的:
#ifndef _SERVER_H
#define _SERVER_H
#include "asynserv.h" // header file with the important lib includes
#include <map>
namespace Connections
{
DWORD WINAPI MainThread(LPVOID lParam); // Main thread
DWORD WINAPI DataThread(LPVOID lParam); // thread that will be created for each client
struct ClientServer // struct to keep a server and a client pair.
{
public:
struct Client* Client;
class Server* Server;
};
struct Client // a struct wrapper to keep clients
{
public:
Client(SOCKET Connection, int BufferSize, UINT ID);
~Client();
SOCKET WorkerSocket;
char Buffer[255];
bool Connected;
int RecvSize;
UINT UID;
void Send(char * Data);
void Disconnect();
};
class Server
{
private:
SOCKET WorkerSocket;
SOCKADDR_IN EndPnt;
UINT ID;
int CBufferSize;
public:
Server(int Port, int Backlog, int BufferSize);
~Server();
__event void ClientRecieved(Client* Clientr, char * RecData);
bool Enabled;
int Port;
int Backlog;
HWND ReqhWnd;
std::map<UINT, Client*> ClientPool;
void WaitForConnections(Server*);
void WaitForData(Client*);
void InvokeClientDC(UINT);
void Startup();
void Shutdown();
};
}
#endif
Server.cpp:
#include "Server.h"
namespace Connections
{
void Server::Startup()
{
WSADATA wsa;
WSAStartup(0x0202, &wsa);
this->WorkerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
this->EndPnt.sin_addr.s_addr = ADDR_ANY;
this->EndPnt.sin_family = AF_INET;
this->EndPnt.sin_port = htons(this->Port);
this->Enabled = true;
this->ID = 0;
bind(this->WorkerSocket, (SOCKADDR*)&this->EndPnt, sizeof(this->EndPnt));
printf("[AsynServer]Bound..\n");
listen(this->WorkerSocket, this->Backlog);
CreateThread(NULL, NULL, &MainThread, this, NULL, NULL);
}
void Server::WaitForConnections(Server * Ser)
{
WSAEVENT Handler = WSA_INVALID_EVENT;
while(Ser->Enabled)
{
Handler = WSACreateEvent();
WSAEventSelect(Ser->WorkerSocket, Handler, FD_ACCEPT);
WaitForSingleObject(Handler, INFINITE);
SOCKET accptsock = accept(Ser->WorkerSocket, NULL, NULL);
Client * NewClient = new Client(accptsock, 255, Ser->ID++);
NewClient->Connected = true;
printf("[AsynServer]Client connected.\n");
ClientServer * OurStruct = new ClientServer();
OurStruct->Server = Ser;
OurStruct->Client = NewClient;
CreateThread(NULL, NULL, &DataThread, OurStruct, NULL, NULL);
}
}
void Server::WaitForData(Client * RClient)
{
WSAEVENT Tem = WSA_INVALID_EVENT;
Tem = WSACreateEvent();
WSAEventSelect(RClient->WorkerSocket, Tem, FD_READ);
while(RClient->Connected)
{
WaitForSingleObject(Tem, INFINITE);
RClient->RecvSize = recv(RClient->WorkerSocket, RClient->Buffer, 255, NULL);
if(RClient->RecvSize > 0)
{
RClient->Buffer[RClient->RecvSize] = '\0';
__raise this->ClientRecieved(RClient, RClient->Buffer);
Sleep(50);
}
}
return;
}
DWORD WINAPI MainThread(LPVOID lParam)
{
((Server*)lParam)->WaitForConnections((Server*)lParam);
return 0;
}
DWORD WINAPI DataThread(LPVOID lParam)
{
ClientServer * Sta = ((ClientServer*)lParam);
Sta->Server->WaitForData(Sta->Client);
return 0;
}
}
现在创建服务器实例并创建主线程后,我可以同时接受客户端并读取它们发送的数据,但是在两个连接之后我的CPU滞后直到100%使用率。 我想我的方法是不正确的,所以我的问题是有人可以指出我的代码中可能存在的缺陷,或者只是为我指出一个不错的异步套接字指南,前提是我已经搜索了一个多星期没有结果(可能是我的)绝望阻碍我选择正确的关键字:|)。 提前致谢,并对这段巨大的代码感到抱歉,在允许的情况下对其进行了修剪。
制造, 简单但完美。
I am trying to write a Server application wrapper, as I would with any application and I've searched for over a week for a at least decent guide or tutorial on asynchronous sockets( this wrapper has to be asynchronous ) and so far what i could do is this:
#ifndef _SERVER_H
#define _SERVER_H
#include "asynserv.h" // header file with the important lib includes
#include <map>
namespace Connections
{
DWORD WINAPI MainThread(LPVOID lParam); // Main thread
DWORD WINAPI DataThread(LPVOID lParam); // thread that will be created for each client
struct ClientServer // struct to keep a server and a client pair.
{
public:
struct Client* Client;
class Server* Server;
};
struct Client // a struct wrapper to keep clients
{
public:
Client(SOCKET Connection, int BufferSize, UINT ID);
~Client();
SOCKET WorkerSocket;
char Buffer[255];
bool Connected;
int RecvSize;
UINT UID;
void Send(char * Data);
void Disconnect();
};
class Server
{
private:
SOCKET WorkerSocket;
SOCKADDR_IN EndPnt;
UINT ID;
int CBufferSize;
public:
Server(int Port, int Backlog, int BufferSize);
~Server();
__event void ClientRecieved(Client* Clientr, char * RecData);
bool Enabled;
int Port;
int Backlog;
HWND ReqhWnd;
std::map<UINT, Client*> ClientPool;
void WaitForConnections(Server*);
void WaitForData(Client*);
void InvokeClientDC(UINT);
void Startup();
void Shutdown();
};
}
#endif
Server.cpp:
#include "Server.h"
namespace Connections
{
void Server::Startup()
{
WSADATA wsa;
WSAStartup(0x0202, &wsa);
this->WorkerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
this->EndPnt.sin_addr.s_addr = ADDR_ANY;
this->EndPnt.sin_family = AF_INET;
this->EndPnt.sin_port = htons(this->Port);
this->Enabled = true;
this->ID = 0;
bind(this->WorkerSocket, (SOCKADDR*)&this->EndPnt, sizeof(this->EndPnt));
printf("[AsynServer]Bound..\n");
listen(this->WorkerSocket, this->Backlog);
CreateThread(NULL, NULL, &MainThread, this, NULL, NULL);
}
void Server::WaitForConnections(Server * Ser)
{
WSAEVENT Handler = WSA_INVALID_EVENT;
while(Ser->Enabled)
{
Handler = WSACreateEvent();
WSAEventSelect(Ser->WorkerSocket, Handler, FD_ACCEPT);
WaitForSingleObject(Handler, INFINITE);
SOCKET accptsock = accept(Ser->WorkerSocket, NULL, NULL);
Client * NewClient = new Client(accptsock, 255, Ser->ID++);
NewClient->Connected = true;
printf("[AsynServer]Client connected.\n");
ClientServer * OurStruct = new ClientServer();
OurStruct->Server = Ser;
OurStruct->Client = NewClient;
CreateThread(NULL, NULL, &DataThread, OurStruct, NULL, NULL);
}
}
void Server::WaitForData(Client * RClient)
{
WSAEVENT Tem = WSA_INVALID_EVENT;
Tem = WSACreateEvent();
WSAEventSelect(RClient->WorkerSocket, Tem, FD_READ);
while(RClient->Connected)
{
WaitForSingleObject(Tem, INFINITE);
RClient->RecvSize = recv(RClient->WorkerSocket, RClient->Buffer, 255, NULL);
if(RClient->RecvSize > 0)
{
RClient->Buffer[RClient->RecvSize] = '\0';
__raise this->ClientRecieved(RClient, RClient->Buffer);
Sleep(50);
}
}
return;
}
DWORD WINAPI MainThread(LPVOID lParam)
{
((Server*)lParam)->WaitForConnections((Server*)lParam);
return 0;
}
DWORD WINAPI DataThread(LPVOID lParam)
{
ClientServer * Sta = ((ClientServer*)lParam);
Sta->Server->WaitForData(Sta->Client);
return 0;
}
}
Now after creating the server instance and creating the main thread, i can accept clients simultaneously and read data they send, but after TWO connections my CPU lags up till 100% usage..
I guess my method is incorrect, so my question is can someone point out a possible flaw in my code, or just point me out a decent guide for asynchronous sockets, provided that i have already searched for over a week with no results( probably my despair is hindering me from choosing the correct keywords :| ).
Thanks in advance and sorry about the huge piece of code, trimmed it as long as it allowed.
Mfg,
SimpleButPerfect.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
第一个错误:
在 Server::WaitForConnections 中,每次执行 while 循环时都会创建 HEVENT (Handler = WSACreateEvent() ),而不破坏它。将 HEVENT 创建移到 while 循环之外。
第二个错误:
你的缓冲区是 255 长(字符),但你这样做:
RClient->Buffer[RClient->RecvSize] = '\0';
其中 RClient->RecvSize 可以是缓冲区大小的精确值 - 这意味着您进行了“缓冲区溢出”分类。
我希望这有帮助。
多米尼克
1st bug:
In Server::WaitForConnections you create the HEVENT (Handler = WSACreateEvent() ) every time the while loop executes without destroying it. Move the HEVENT creation outside the while loop.
2nd bug:
Your buffer is 255 long (char) but you do this:
RClient->Buffer[RClient->RecvSize] = '\0';
where RClient->RecvSize can be the exaclty of the size of your buffer - that means you make a classis "buffer overrun".
I hope this helps.
Dominik