Код:
//Цыкл прослушивания новых пакетов
//##############################################################################
Work_While:
if(not Terminated)then
begin
//Проверка паузы
if(FPaused)then begin
sleep(1000);
goto No_NewConnect;
end;
//
//
//Если клиентов больше нуля
if(Network.ClientsCount>0)then
begin
//DebugTrace('- Recv='+inttostr(Network.ClientsCount)+' = '+inttostr(Network.ClientsFree[ClientIndex]));
//!!!!!!!!!!!!!!!!!!!!!!!!!
ClientIndex := ClientIndex+1;
if(ClientIndex >= Network.ClientsCount)then
ClientIndex := 0;
//
ClientIndex1 := Network.ClientsFree[ClientIndex];
//
time:=RDTSC();
//Log.AddLogLine(lfErrorLog,'КН - '+inttostr(ClientIndex1+1),ltrCriticalError);
//
ClientState := Network.Clients[ClientIndex1].State;
//
//
if(ClientState = cnsWite)then
begin
//Проверка доступности данных клиента
//int := Recv(Network.Clients[Index1ToIndex(ClientIndex)].ClientSocket, Network.Clients[Index1ToIndex(ClientIndex)].BuffData[0] , TClientsBuffSize, 0);
int := Recv(Network.Clients[ClientIndex1].ClientSocket, Network.Clients[ClientIndex1].BuffData[Network.Clients[ClientIndex1].BuffDataBase] , TClientsBuffSize-Network.Clients[ClientIndex1].BuffDataBase, 0);
if (int = INVALID_SOCKET) then begin
if(WSAGetLastError = WSAEWOULDBLOCK)then
goto Cont_Recv;
//!!10054 - потеря связи с клиентом
//
if(WSAGetLastError = 10054) or (WSAGetLastError = 10053)then begin
//Очистка структур клиентов
Network.DisconnectClient(ClientIndex1+1);
goto Cont_Recv;
end;
//
Log.AddLogLine(lfErrorLog,'(Recv) ERROR CODE: '+inttostr(WSAGetLastError)+'',ltrFullError);
//
Network.DisconnectClient(ClientIndex1+1);
goto Cont_Recv;
end else begin
Network.Clients[ClientIndex1].BuffDataBase := 0;
end;
//
//Получение данных от клиента
if(int = 0)then
begin
//Disconnect клиент отключился
Network.SetState(ClientIndex1+1,cnsDisconectClient);
//Вызов обработчика отключения клиента
if Assigned(Network.FOnDisconnectClient)then
Network.FOnDisconnectClient(ClientIndex1+1);
//
//Уничтожение(отключение) windows сокета
CloseSocket(Network.Clients[ClientIndex1].ClientSocket);
//
if(ClientState <> cnsWork)then
begin
Network.DOnFreeClient(ClientIndex1+1);
end;
//
Log.AddLogLine(lfErrorLog,'Отключение - '+inttostr(ClientIndex1+1),ltrCriticalError);
//
end else
begin
if(ClientState = cnsWite)then
begin
//Resive даные полученны и скопированны в буфер
//DebugTrace('- Recv=='+inttostr(int));
//
Network.Clients[ClientIndex1].BuffDataLength := int;
//Переводим клиента в режим обработки
//Network.SetState(Network.ClientsFree[ClientIndex]+1,cnsWork);
//
if Assigned(Network.FOnReciveClient)then
Network.FOnReciveClient(ClientIndex1+1);
//Переводим клиента в режим ожидания
if(Network.Clients[ClientIndex1].State = cnsWork)then
Network.SetState(ClientIndex1+1,cnsWite);
//
Log.AddLogLine(lfErrorLog,'Прием - '+inttostr(ClientIndex1+1),ltrCriticalError);
//
end;
end;
end;
Cont_Recv:
ClientState := Network.Clients[ClientIndex1].State;
//Серверное отключение клиента
if(ClientState >= cnsDisconectServer)then begin
//showmessage('-'+inttostr(integer(ClientState)));
if(ClientState = cnsDisconectServerSend)then begin
Network.TransmitClientData(ClientIndex1+1,Network.Clients[ClientIndex1].BuffData,Network.Clients[ClientIndex1].BuffDataLength);
end;
//Вызов обработчика отключения клиента
if Assigned(Network.FOnDisconnectClient)then
Network.FOnDisconnectClient(ClientIndex1+1);
//
//Уничтожение(отключение) windows сокета
if(ClientState = cnsDisconectServer)then
CloseSocket(Network.Clients[ClientIndex1].ClientSocket);
//
Log.AddLogLine(lfErrorLog,'ОтключениеС - '+inttostr(ClientIndex1+1),ltrCriticalError);
//
Network.DOnFreeClient(ClientIndex1+1);
goto No_RecvClient;
end;
//
time:=RDTSC()-time;
//Log.AddLogLine(lfErrorLog,'КК - '+inttostr(ClientIndex1+1)+'='+inttostr(time),ltrCriticalError);
end;
//
No_RecvClient:
//
time:=RDTSC();
//Log.AddLogLine(lfErrorLog,'КПод - '+inttostr(0),ltrCriticalError);
//Принимаем новое подключение
//Network.Clients[ClientIndex1-1].ClientSocket := accept(WinSocket, @Network.Clients[ClientIndex1-1].ClientAddr, @sizeAddr);
clientSocket := accept(WinSocket, @clientAddr, @sizeAddr);
if (clientSocket = INVALID_SOCKET) then
begin
if(WSAGetLastError = WSAEWOULDBLOCK)then
goto No_NewConnect;
//
Log.AddLogLine(lfErrorLog,'(Accept) ERROR CODE: '+inttostr(WSAGetLastError)+'',ltrWarningError);
goto No_NewConnect;
//
end;
//
//Выделение структур под клиента
ClientIndex1 := Network.AddClient();
if(ClientIndex1 = 0)then
begin
//Буфер под клиента не выделен
if(Network.ClientsCount >= TMaxClients)then begin
Log.AddLogLine(lfErrorLog,'Превышено максимальное количество клиентов сервера',ltrFullError);
end else begin
Log.AddLogLine(lfErrorLog,'Структуры под нового клиента не выделенны',ltrFullError);
end;
//Сброс подключения
CloseSocket(clientSocket);
goto No_NewConnect;
end;
//
//AddLogNetDump(lfNetDump, nil, 0);
Network.Clients[ClientIndex1-1].ClientSocket := clientSocket;
Network.Clients[ClientIndex1-1].ClientAddr := clientAddr;
//Заполнение структуры клиента
//ClientNetwork.Port := clientAddr.sin_port;
//ClientNetwork.IP := inet_ntoa(clientAddr.sin_addr);
Network.SetState(ClientIndex1,cnsWite);
//Вызов события создания клиента
if Assigned(Network.FOnCreateClient)then
Network.FOnCreateClient(ClientIndex1);
//Вызов события подключения клиента
if Assigned(Network.FOnConnectClient)then
Network.FOnConnectClient(ClientIndex1);
//
time:=RDTSC()-time;
//Log.AddLogLine(lfErrorLog,'КПодК - '+inttostr(ClientIndex1)+'='+inttostr(time),ltrCriticalError);
if(ClientIndex1 = 4)then
begin
//ClientIndex1 := Network.ClientsFree[ClientIndex];
//showmessage('Error' +inttostr(Integer(Network.Clients[Network.ClientsFree[0]].State)) +'='+inttostr(Network.ClientsFree[0])+' - '+inttostr(Integer(Network.Clients[Network.ClientsFree[1]].State))+'='+inttostr(Network.ClientsFree[1])+' - '+inttostr(Integer(Network.Clients[Network.ClientsFree[2]].State))+'='+inttostr(Network.ClientsFree[2])+' - '+inttostr(Integer(Network.Clients[Network.ClientsFree[3]].State))+'='+inttostr(Network.ClientsFree[3])+' - '+inttostr(Integer(Network.Clients[Network.ClientsFree[4]].State))+'='+inttostr(Network.ClientsFree[4])+'');
end;
//
No_NewConnect:
//
sleep(10);
goto Work_While;
end;
//
End_Proc:
FWork := false;
end;
Извините за отладочный мусор в коде.
Код (если запускать отдельно от среды) вроде рабочий. Но со стабильностью я не уверен.
Подскажите насколько адекватна схема переиспользования памяти(структур) клиентов?
И как еще можно дописать код в procedure TNetworkThread.Execute(); чтоб он работал стабильно, и не упал от ошибок памяти или еще чего-то?
Буду благодарен за любые хорошие советы по доработке кода, особенно в ключе обработки ошибок.