end
else
begin
if StrLen <= 0 then
begin
LogMessage('Неверная длина строки от клиента: ' +
IntToStr(StrLen));
LoopExit:= True;
Break;
end;
BytesLeft:= StrLen;
SetLength(Str, StrLen);
end;
end
else Inc(Offset, L);
Inc(P, L);
end;
// Проверяем, был ли аварийный выход из внутреннего цикла,
// и если был, выходим и из внешнего, завершая работу
// с клиентом
if LoopExit then Break;
end
else if RecvRes = 0 then
begin
LogMessage('Клиент закрыл соединение ');
Break;
end
else
begin
if WSAGetLastError <> WSAEWOULDBLOCK then
begin
LogMessage('Ошибка при получении данных от клиента: ' +
GetErrorString);
end;
end;
end;
// Сокет готов к передаче данных
if NetEvents.lNetworkEvents and FD_WRITE <> 0 then
begin
if NetEvents.iErrorCode[FD_WRITE_BIT] <> 0 then
begin
LogMessage('Ошибка в событии FD_WRITE: ' +
GetErrorString(NetEvents.iErrorCode[FD_WRITE_BIT)));
Break;
end;
// Отправляем то, что лежит в буфере
if not DoSendBuf then Break;
end;
if NetEvents.lNetworkEvents and FD_CLOSE <> 0 then
begin
// Клиент закрыл соединение
if NetEvents.iErrorCode[FD_CLOSE_BIT] <> 0 then
begin
LogMessage('Ошибка в событии FD_CLOSE: ' +
GetErrorString(NetEvents.iErrorCode[FD_CLOSE_BIT]));
Break;
end;
LogMessage('Клиент закрыл соединение');
shutdown(FSocket, SD_BOTH);
Break;
end;
end;
WSA_WAIT_FAILED: begin
LogMessage('Ошибка при ожидании сообщения: ' + GetErrorString);
Break;
end;
else begin
LogMessage(
'Внутренняя ошибка сервера — неверный результат ожидания ' +
IntToStr(WaitRes));
Break;
end;
end;
until False;
closesocket(FSocket);
LogMessage('Нить остановлена');
end;
// Функция возвращает True, если нить завершилась
function TClientThread.GetFinished: Boolean;
begin
// Ждем окончания работы нити с нулевым тайм-аутом.
// Если нить завершена, вернется WAIT_OBJECT_0.
// Если еще работает, вернется WAIT_TIMEOUT.
Result:= WaitForSingleObject(Handle, 0) = WAIT_OBJECT_0;
end;
// Метод для остановки нити извне.
// Взводим соответствующее событие, а остальное сделаем
// при обработке события
procedure TClientThread.StopThread;
WSASetEvent(FEvents[0]);
end;
Модуль WinSock2_Events
, появившийся в списке uses
, содержит объявления констант, типов и функций из WinSock 2, которые понадобятся в программе. Модуль ShutdownConst
содержит объявления констант для функции shutdown
, которые отсутствуют в модуле WinSock Delphi 5 и более ранних версиях — этот модуль нам понадобился, чтобы программу можно было откомпилировать в Delphi 5.