모든 응용 프로그램 에서처럼 서버 응용 프로그램 래퍼를 작성하려고합니다. 적어도 1 주일 이상 비례 소켓 또는 자습서를 검색했습니다. 래퍼는 비동기 수있다) 지금까지 내가 무엇을 할 수 있는지 이것이다 :비동기 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 l agws 최대 100 % 사용량까지. 내 방법이 잘못되었습니다, 그래서 내 질문에 누군가가 내 코드에 가능한 결함을 지적하거나 그냥 비동기 소켓에 대한 괜찮은 가이드를 가리킨 수있는 제공 한 이미 제공 한 결과가없는 1 주일 (아마도 절망은 올바른 키워드를 선택하는 것을 방해하고 있습니다.). 거대한 코드 조각에 대해 미리 감사 드리며, 허용 된 한 그것을 다듬습니다.
Mfg, SimpleButPerfect.
답장을 보내 주셔서 감사합니다.하지만 루프 외부에서 처리기를 만들면 WSAEvent가 발생할 때까지 기다리지 않고 루프가 시작됩니다. SimpleButPerfect. – SimpleButPerfect
WSAEvent()에 의해 생성 된 이벤트가 수동 재설정 이벤트이고 어디에서나 재설정하지 않기 때문입니다. 그래서 그것은 한 번 설정되면 다음 설정을 유지합니다. –
코드를 간과 했으므로 결함을 지적 해 주셔서 감사합니다. – SimpleButPerfect