constructor TClientThread.Create(ClientSocket: TSocket; const ClientAddr: TSockAddr);
begin
FSocket := ClientSocket;
// Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ Π°Π΄ΡΠ΅Ρ ΠΈ Π½ΠΎΠΌΠ΅Ρ ΠΏΠΎΡΡΠ° ΠΊΠ»ΠΈΠ΅Π½ΡΠ°.
// ΠΡΠΎΡ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ Π±ΡΠ΄Π΅Ρ Π΄ΠΎΠ±Π°Π²Π»ΡΡΡΡΡ ΠΊΠΎ Π²ΡΠ΅ΠΌ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡΠΌ Π² Π»ΠΎΠ³
// ΠΎΡ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°.
FHeader :=
'Π‘ΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ ΠΎΡ ΠΊΠ»ΠΈΠ΅Π½ΡΠ° ' + inet_ntoa(ClientAddr.sin_addr) +
': ' + IntToStr(ntohs(ClientAddr.sin_port)) + ': ';
// Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΡΠΎΠ±ΡΡΠΈΡ ΠΈ ΠΏΡΠΈΠ²ΡΠ·ΡΠ²Π°Π΅ΠΌ ΠΏΠ΅ΡΠ²ΠΎΠ΅ ΠΈΠ· Π½ΠΈΡ ΠΊ ΡΠΎΠΊΠ΅ΡΡ
FEvents[0] := WSACreateEvent;
if FEvents[0] = WSA_INVALID_EVENT then
raise ESocketError.Create(
FHeader + 'ΠΡΠΈΠ±ΠΊΠ° ΠΏΡΠΈ ΡΠΎΠ·Π΄Π°Π½ΠΈΠΈ ΡΠΎΠ±ΡΡΠΈΡ: ' + GetErrorString);
FEvents[1] := WSACreateEvent;
if FEvents[1] = WSA_INVALID_EVENT then
raise ESocketError.Create(
FHeader + 'ΠΡΠΈΠ±ΠΊΠ° ΠΏΡΠΈ ΡΠΎΠ·Π΄Π°Π½ΠΈΠΈ ΡΠΎΠ±ΡΡΠΈΡ: ' + GetErrorString);
FEvents[2] := WSACreateEvent;
if FEvents[2] = WSA_INVALID_EVENT then raise
ESocketError.Create(
FHeader + 'ΠΡΠΈΠ±ΠΊΠ° ΠΏΡΠΈ ΡΠΎΠ·Π΄Π°Π½ΠΈΠΈ ΡΠΎΠ±ΡΡΠΈΡ: ' + GetErrorString);
if WSAEventSelect(FSocket, FEvents[2], FD_READ or FD_WRITE or FD_CLOSE) =
SOCKET_ERROR then
raise ESocketError.Create(
FHeader + 'ΠΡΠΈΠ±ΠΊΠ° ΠΏΡΠΈ ΠΏΡΠΈΠ²ΡΠ·ΡΠ²Π°Π½ΠΈΠΈ ΡΠΎΠΊΠ΅ΡΠ° ΠΊ ΡΠΎΠ±ΡΡΠΈΡ: ' + GetErrorString);
FSendBufSection := TCriticalSection.Create;
// ΠΠ±ΡΠ΅ΠΊΡ ΡΡΠΎΠΉ Π½ΠΈΡΠΈ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠ΄Π°Π»ΡΡΡΡΡ ΡΠ°ΠΌ
FreeOnTerminate := False;
inherited Create(False);
end;
destructor TClientThread.Destroy;
begin
FSendBufSection.Free;
WSACloseEvent(FEvents[0]);
WSACloseEvent(FEvents[1]);
WSACloseEvent(FEvents[2]);
inherited;
end;
// Π€ΡΠ½ΠΊΡΠΈΡ Π΄ΠΎΠ±Π°Π²Π»ΡΠ΅Ρ ΡΡΡΠΎΠΊΡ Π² Π±ΡΡΠ΅Ρ Π΄Π»Ρ ΠΎΡΠΏΡΠ°Π²ΠΊΠΈ
procedure TClientThread.SendString(const S: string);
begin
FSendBufSection.Enter;
try
FSendBuf := FSendBuf + S + #0;
finally
FSendBufSection.Leave;
end;
LogMessage('Π‘ΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ "' + S + '" ΠΏΠΎΡΡΠ°Π²Π»Π΅Π½ΠΎ Π² ΠΎΡΠ΅ΡΠ΅Π΄Ρ Π΄Π»Ρ ΠΎΡΠΏΡΠ°Π²ΠΊΠΈ');
// ΠΠ·Π²ΠΎΠ΄ΠΈΠΌ ΡΠΎΠ±ΡΡΠΈΠ΅, ΠΊΠΎΡΠΎΡΠΎΠ΅ Π³ΠΎΠ²ΠΎΡΠΈΡ, ΡΡΠΎ Π½ΡΠΆΠ½ΠΎ ΠΎΡΠΏΡΠ°Π²Π»ΡΡΡ Π΄Π°Π½Π½ΡΠ΅
WSASetEvent(FEvents[1]);
end;
// ΠΡΠΏΡΠ°Π²ΠΊΠ° Π²ΡΠ΅Ρ Π΄Π°Π½Π½ΡΡ , Π½Π°ΠΊΠΎΠΏΠ»Π΅Π½Π½ΡΡ Π² Π±ΡΡΠ΅ΡΠ΅
// Π€ΡΠ½ΠΊΡΠΈΡ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ False, Π΅ΡΠ»ΠΈ ΠΏΡΠΎΠΈΠ·ΠΎΡΠ»Π° ΠΎΡΠΈΠ±ΠΊΠ°,
// ΠΈ True, Π΅ΡΠ»ΠΈ Π²ΡΠ΅ Π² ΠΏΠΎΡΡΠ΄ΠΊΠ΅
function TClientThread.DoSendBuf: Boolean;
var
SendRes: Integer;
begin
FSendBufSection.Enter;
try
// ΠΡΠ»ΠΈ ΠΎΡΠΏΡΠ°Π²Π»ΡΡΡ Π½Π΅ΡΠ΅Π³ΠΎ, Π²ΡΡ ΠΎΠ΄ΠΈΠΌ
if FSendBuf = '' then
begin
Result := True;
Exit;
end;
// ΠΡΡΠ°Π΅ΠΌΡΡ ΠΎΡΠΏΡΠ°Π²ΠΈΡΡ Π²ΡΠ΅, ΡΡΠΎ Π΅ΡΡΡ Π² Π±ΡΡΠ΅ΡΠ΅
SendRes := send(FSocket, FSendBuf[1], Length(FSendBuf), 0);
if SendRes > 0 then
begin
// Π£Π΄Π°Π»ΡΠ΅ΠΌ ΠΈΠ· Π±ΡΡΠ΅ΡΠ° ΡΡ ΡΠ°ΡΡΡ, ΠΊΠΎΡΠΎΡΠ°Ρ ΠΎΡΠΏΡΠ°Π²ΠΈΠ»Π°ΡΡ ΠΊΠ»ΠΈΠ΅Π½ΡΡ
Delete(FSendBuf, 1, SendRes);
Result := True;
end
else
begin
Result := WSAGetLastError = WSAEWOULDBLOCK;
if not Result then
LogMessage('ΠΡΠΈΠ±ΠΊΠ° ΠΏΡΠΈ ΠΎΡΠΏΡΠ°Π²ΠΊΠ΅ Π΄Π°Π½Π½ΡΡ : ' + GetErrorString);
end;
finally
FSendBufSection.Leave;
end;
end;
procedure TClientThread.Execute;
const
// ΡΠ°Π·ΠΌΠ΅Ρ Π±ΡΡΠ΅ΡΠ° Π΄Π»Ρ ΠΏΡΠΈΠ΅ΠΌΠ° ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΈ
RecvBufSize = 4096;
var
// ΠΡΡΠ΅Ρ Π΄Π»Ρ ΠΏΡΠΈΠ΅ΠΌΠ° ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΉ
RecvBuf: array[0..RecvBufSize - 1] of Byte;
RecvRes: Integer;
NetEvents: TWSANetworkEvents;
// ΠΠΎΠ»ΡΡΠ΅Π½Π½Π°Ρ ΡΡΡΠΎΠΊΠ°
Str: string;
// ΠΠ»ΠΈΠ½Π° ΠΏΠΎΠ»ΡΡΠ΅Π½Π½ΠΎΠΉ ΡΡΡΠΎΠΊΠΈ
StrLen: Integer;
// ΠΡΠ»ΠΈ ReadLength = True, ΠΈΠ΄Π΅Ρ ΡΡΠ΅Π½ΠΈΠ΅ Π΄Π»ΠΈΠ½Ρ ΡΡΡΠΎΠΊΠΈ,
// Π΅ΡΠ»ΠΈ False - ΡΠ°ΠΌΠΎΠΉ ΡΡΡΠΎΠΊΠΈ
ReadLength: Boolean;
// Π‘ΠΌΠ΅ΡΠ΅Π½ΠΈΠ΅ ΠΎΡ Π½Π°ΡΠ°Π»Π° ΠΏΡΠΈΠ΅ΠΌΠ½ΠΈΠΊΠ°
Offset: Integer;
// Π§ΠΈΡΠ»ΠΎ Π±Π°ΠΉΡΠΎΠ², ΠΎΡΡΠ°Π²ΡΠΈΡ ΡΡ ΠΏΡΠΈ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΠΈ Π΄Π»ΠΈΠ½Ρ ΡΡΡΠΎΠΊΠΈ ΠΈΠ»ΠΈ ΡΠ°ΠΌΠΎΠΉ ΡΡΡΠΎΠΊΠΈ
BytesLeft: Integer;
Π : Integer;
I: Integer;
LoopExit: Boolean;
WaitRes: Cardinal;
begin
LogMessage('Π‘ΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΎ');
ReadLength := True;
Offset := 0;
BytesLeft := SizeOf(Integer);
repeat
WaitRes := WSAWaitForMultipleEvents(3, @FEvents, False, WSA_INFINITE, False);
case WaitRes of
WSA_WAIT_EVENT_0: begin
// ΠΠ°ΠΊΡΡΠ²Π°Π΅ΠΌ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ Ρ ΠΊΠ»ΠΈΠ΅Π½ΡΠΎΠΌ ΠΈ ΠΎΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ Π½ΠΈΡΡ
LogMessage('ΠΠΎΠ»ΡΡΠ΅Π½ ΡΠΈΠ³Π½Π°Π» ΠΎΠ± ΠΎΡΡΠ°Π½ΠΎΠ²ΠΊΠ΅ Π½ΠΈΡΠΈ');
shutdown(FSocket, SD_BOTH);
Break;
end;
WSA_WAIT_EVENT_0 + 1:
begin
// Π‘Π±ΡΠ°ΡΡΠ²Π°Π΅ΠΌ ΡΠΎΠ±ΡΡΠΈΠ΅ ΠΈ ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅ΠΌ Π΄Π°Π½Π½ΡΠ΅
WSAResetEvent(FEvents[1]);
if not DoSendBuf then Break;
end;
WSA_WAIT_EVENT_0 + 2: begin
// ΠΡΠΎΠΈΠ·ΠΎΡΠ»ΠΎ ΡΠΎΠ±ΡΡΠΈΠ΅, ΡΠ²ΡΠ·Π°Π½Π½ΠΎΠ΅ Ρ ΡΠΎΠΊΠ΅ΡΠΎΠΌ.
// ΠΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ, ΠΊΠ°ΠΊΠΎΠ΅ ΠΈΠΌΠ΅Π½Π½ΠΎ, ΠΈ Π·Π°ΠΎΠ΄Π½ΠΎ ΡΠ±ΡΠ°ΡΡΠ²Π°Π΅ΠΌ Π΅Π³ΠΎ
if WSAEnumNetworkEvents(FSocket, FEvents[2], NetEvents) = SOCKET_ERROR then
begin
LogMessage('ΠΡΠΈΠ±ΠΊΠ° ΠΏΡΠΈ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΠΈ ΡΠΏΠΈΡΠΊΠ° ΡΠΎΠ±ΡΡΠΈΠΉ: ' + GetErrorString);
Break;
end;
if NetEvents.lNetworkEvents and FD_READ <> 0 then
begin
if NetEvents.iErrorCode[FD_READ_BIT] <> 0 then
begin
LogMessage('ΠΡΠΈΠ±ΠΊΠ° Π² ΡΠΎΠ±ΡΡΠΈΠΈ FD_READ: ' +
GetErrorString(NetEvents.iErrorCode[FD_READ_BIT]));
Break;
end;
// Π Π±ΡΡΠ΅ΡΠ΅ ΡΠΎΠΊΠ΅ΡΠ° Π΅ΡΡΡ Π΄Π°Π½Π½ΡΠ΅.
// ΠΠΎΠΏΠΈΡΡΠ΅ΠΌ Π΄Π°Π½Π½ΡΠ΅ ΠΈΠ· Π±ΡΡΠ΅ΡΠ° ΡΠΎΠΊΠ΅ΡΠ° Π² ΡΠ²ΠΎΠΉ Π±ΡΡΠ΅Ρ RecvBuf
RecvRes := recv(FSocket, RecvBuf, SizeOf(RecvBuf), 0);
if RecvRes > 0 then
begin
P := 0;
// ΠΡΠ° ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½Π°Ρ Π½ΡΠΆΠ½Π° ΠΏΠΎΡΠΎΠΌΡ, ΡΡΠΎ Π·Π΄Π΅ΡΡ ΠΏΠΎΡΠ²Π»ΡΠ΅ΡΡΡ
// Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΠΉ ΡΠΈΠΊΠ», ΠΏΡΠΈ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΈΠΈ ΠΎΡΠΈΠ±ΠΊΠΈ Π² ΠΊΠΎΡΠΎΡΠΎΠΌ Π½ΡΠΆΠ½ΠΎ
// Π²ΡΠΉΡΠΈ ΠΈ ΠΈΠ· Π²Π½Π΅ΡΠ½Π΅Π³ΠΎ ΡΠΈΠΊΠ»Π° ΡΠΎΠΆΠ΅. Π’Π°ΠΊ ΠΊΠ°ΠΊ Π² Delphi Π½Π΅Ρ
// ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΈΠΈ ΡΠΈΠΏΠ° Break(2) Π² ΠΠ΄Π΅, ΠΏΡΠΈΡ ΠΎΠ΄ΠΈΡΡΡ ΠΏΡΠΈΠ±Π΅Π³Π°ΡΡ
// ΠΊ ΡΠ°ΠΊΠΈΠΌ ΡΠΏΠΎΡΠΎΠ±Π°ΠΌ: Π΅ΡΠ»ΠΈ Π½ΡΠΆΠ΅Π½ Π²ΡΡ ΠΎΠ΄ ΠΈΠ· Π²Π½Π΅ΡΠ½Π΅Π³ΠΎ ΡΠΈΠΊΠ»Π°,
// Π²ΠΎ Π²Π½ΡΡΡΠ΅Π½Π½Π΅ΠΌ ΡΠΈΠΊΠ»Π΅ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ LoopExit := True,
// Π° ΠΏΠΎΡΠ»Π΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π²Π½ΡΡΡΠ΅Π½Π½Π΅Π³ΠΎ ΡΠΈΠΊΠ»Π° ΠΏΡΠΎΠ²Π΅ΡΡΠ΅ΡΡΡ
// Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΡΡΠΎΠΉ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΉ ΠΈ ΠΏΡΠΈ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎΡΡΠΈ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ
// Π²ΡΡ ΠΎΠ΄ ΠΈ ΠΈΠ· Π³Π»Π°Π²Π½ΠΎΠ³ΠΎ ΡΠΈΠΊΠ»Π°.
LoopExit := False;
// Π ΡΡΠΎΠΌ ΡΠΈΠΊΠ»Π΅ ΠΌΡ ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌ Π΄Π°Π½Π½ΡΠ΅ ΠΈΠ· Π±ΡΡΠ΅ΡΠ°
// ΠΈ ΡΠ°ΡΠΊΠΈΠ΄ΡΠ²Π°Π΅ΠΌ ΠΈΡ ΠΏΠΎ ΠΏΡΠΈΡΠΌΠ½ΠΈΠΊΠ°ΠΌ - Str ΠΈ StrLen.
while Π < RecvRes do
begin
// ΠΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅ΠΌ, ΡΠΊΠΎΠ»ΡΠΊΠΎ Π±Π°ΠΉΡΠΎΠ² Π½Π°ΠΌ Ρ ΠΎΡΠ΅Π»ΠΎΡΡ Π±Ρ ΡΠΊΠΎΠΏΠΈΡΠΎΠ²Π°ΡΡ
L := BytesLeft;
// ΠΡΠ»ΠΈ Π² Π±ΡΡΠ΅ΡΠ΅ Π½Π΅Ρ ΡΠ°ΠΊΠΎΠ³ΠΎ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π°,
// Π΄ΠΎΠ²ΠΎΠ»ΡΡΡΠ²ΡΠ΅ΠΌΡΡ ΡΠ΅ΠΌ, ΡΡΠΎ Π΅ΡΡΡ
if Π + L > RecvRes then L := RecvRes - P;
// ΠΠΎΠΏΠΈΡΡΠ΅ΠΌ Π² ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠΈΠΉ ΠΏΡΠΈΠ΅ΠΌΠ½ΠΈΠΊ
if ReadLength then
Move(RecvBuf[P], (PChar(@StrLen) + Offset)^, L)
else Move(RecvBuf[P], Str(Offset + 1), L);
Dec(BytesLeft, L);
// ΠΡΠ»ΠΈ ΠΏΡΠΎΡΠΈΡΠ°Π»ΠΈ Π²ΡΠ΅, ΡΡΠΎ Ρ ΠΎΡΠ΅Π»ΠΈ,
// ΠΏΠ΅ΡΠ΅Ρ ΠΎΠ΄ΠΈΠΌ ΠΊ ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΌΡ
if BytesLeft = 0 then
begin
ReadLength := not ReadLength;
Offset := 0;
// ΠΡΠ»ΠΈ Π·Π°ΠΊΠΎΠ½ΡΠ΅Π½ΠΎ ΡΡΠ΅Π½ΠΈΠ΅ ΡΡΡΠΎΠΊΠΈ, Π½ΡΠΆΠ½ΠΎ Π²ΡΠ²Π΅ΡΡΠΈ Π΅Π΅
if ReadLength then
begin
LogMessage('ΠΠΎΠ»ΡΡΠ΅Π½Π° ΡΡΡΠΎΠΊΠ°: ' + Str);
BytesLeft := SizeOf(Integer);
// Π€ΠΎΡΠΌΠΈΡΡΠ΅ΠΌ ΠΎΡΠ²Π΅Ρ ΠΈ Π·Π°ΠΏΠΈΡΡΠ²Π°Π΅ΠΌ Π΅Π³ΠΎ Π² Π±ΡΡΠ΅Ρ
Str :=
AnsiUpperCase(StringReplace(Str, #0, '#0',
[rfReplaceAll])) + '(AsyncEvent server)';
SendString(Str);
Str := '';
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