Zmieniłem teraz na coś takiego:
void Client::Thread(Client* thisClient)
{
BYTE* buffer = new BYTE[1 * 1024 * 1024 * 6];
while(!thisClient->clientSocket)
Sleep(1);
int recvBytes = 0;
// Dopóki otrzymuje się pakiety > 0 i klient jest połączony z serverem
while(((recvBytes = recv(thisClient->clientSocket,(char*)buffer,4,0)) > 0) && thisClient->clientSocket)
{
bool breakLoop = false;
// Długość pakietu
UINT32 packetLength = (buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24) + 4;
UINT32 dataLength = (buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24);
while(recvBytes != packetLength)
{
int recvNow = recv(thisClient->clientSocket,(char*)(buffer+recvBytes),packetLength-recvBytes,0);
if(recvNow <= 0)
{
breakLoop = true;
break;
}
recvBytes += recvNow;
}
if(breakLoop)
break;
ONRECV onRecvFunction = (ONRECV)thisClient->onRecvFunction;
onRecvFunction(buffer);
thisClient->packetReceived++;
Sleep(1);
}
MessageBox(NULL,"close","d",MB_OK);
// Klient jest rozłączony z serverem to można samemu rozłączyć
thisClient->Close();
ONCLOSE onCloseFunction = (ONCLOSE)thisClient->onCloseFunction;
onCloseFunction();
delete[] buffer;
}
Jak server się rozłączy to powinien sie wysiwetlic message box z napisem "close", jednak sie nie wyswietla i na dodatek klient zuzywa 100 % CPU,
btw, moze to cos ma do rzeczy:
mam jeszcze jeden wątek, ktory odnawia połączenie z serverem, gdyby server się wyłączył i za iles tam czasu włączył.
void Gad::Thread(Gad* gad)
{
// Wyslanie pakietu powitalnego
protocol->sendWelcome();
while(true)
{
if(!protocol->client->IsConnected())
{
// Odnowienie winsocka (jakby bylo wywolane WSACleanup() )
protocol->StartWinsock();
// Proba polaczenia z serverem
protocol->client->Renew();
// Wyslanie pakietu powitalnego
protocol->sendWelcome();
}
Sleep(2000);
}
}
Tak wyglada konstruktor obiektu Client
Client::Client(Protocol* protocol, void* onRecvFunction, void* onCloseFunction, const char* ip, int port)
{
this->packetSent = 0;
this->packetReceived = 0;
this->clientSocket = 0;
this->onRecvFunction = onRecvFunction;
this->onCloseFunction = onCloseFunction;
this->ip = new char[30];
strcpy(this->ip,ip);
this->port = port;
clientSocket = socket(AF_INET,SOCK_STREAM,0);
sockaddr_in sin;
hostent* host;
host = gethostbyname(ip);
if(!host)
{
Close();
WSACleanup();
return;
}
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ((in_addr*)(host->h_addr))->s_addr;
sin.sin_port = htons(port);
if(connect(clientSocket,(sockaddr*)&sin,sizeof(sin)) == SOCKET_ERROR)
{
Close();
WSACleanup();
return;
}
// Tworzenie wątku
hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Client::Thread,(DWORD*)this,0,NULL);
}
A tutaj niektore funkcje
bool Protocol::StartWinsock()
{
WORD wVersion;
WSADATA wsaData;
wVersion = MAKEWORD(2,0);
if(WSAStartup(wVersion,&wsaData) != ERROR_SUCCESS)
{
WSACleanup();
return false;
}
if((LOBYTE(wsaData.wVersion)!=2) || (HIBYTE(wsaData.wVersion)!=0))
{
WSACleanup();
return false;
}
return true;
}
void Client::Close()
{
if(clientSocket)
{
closesocket(clientSocket);
clientSocket = 0;
}
}
void Client::Renew()
{
if(hThread)
{
TerminateThread(hThread,0);
hThread = 0;
}
Close();
clientSocket = socket(AF_INET,SOCK_STREAM,0);
sockaddr_in sin;
hostent* host;
host = gethostbyname(ip);
if(!host)
{
Close();
WSACleanup();
return;
}
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ((in_addr*)(host->h_addr))->s_addr;
sin.sin_port = htons(port);
if(connect(clientSocket,(sockaddr*)&sin,sizeof(sin)) == SOCKET_ERROR)
{
Close();
WSACleanup();
return;
}
hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Client::Thread,(DWORD*)this,0,NULL);
}