Нет необходимости проверять соединение. Если бы клиент был фактически отключен, он больше не был бы в списке Connections[]
сервера, когда ваш обработчик OnTimer
запущен. У вас должен быть обработчик OnClientDisconnect
, назначенный для TServerSocket
для удаления клиента из TListView
.
Если по какой-то причине клиент все еще был в списке Connections[]
(т. Е. Потому чтобазовое соединение было потеряно, но TServerSocket
еще не обнаружило его), тогда сокет будет просто кэшировать все исходящие данные до тех пор, пока его исходящий буфер не заполнится, затем он начнет возвращать WSAWOULDBLOCK
ошибок для каждой отправки. В конце концов, ОС истечет время ожидания мертвого соединения и TServerSocket
удалит его из списка Connections[]
, вызвав событие OnClientDisconnect
.
По крайней мере, в показанном вами коде вы должныобновите ваш цикл отправки на Close()
любой сокет, который на самом деле не удается отправить, вызывая событие OnClientDisconnect
для удаления этого клиента из TListView
, например:
procedure TMainForm.ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket);
var
Item: TListItem;
begin
Item := ListView1.Items.Add;
Item.Data := Socket;
...
end;
procedure TMainForm.ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket);
var
Item: TListItem;
begin
Item := ListView1.FindData(0, Socket, True, False);
if Item <> nil then
Item.Delete;
end;
procedure TMainForm.Timer1Timer(Sender: TObject);
const
s: AnsiString = 'ping' + #13#10;
var
Item: TListItem;
Socket: TCustomWinSocket;
p: PAnsiChar;
i, len, sent: Integer;
begin
for i := 0 to ListView1.Items.Count - 1 do
begin
Item := ListView1.Items[i];
Item.SubItems.Objects[2] := TObject(GetTickCount);
Socket := TCustomWinSocket(Item.Data);
try
// SendText() does not handle partial sends, or Unicode strings...
//Socket.SendText('ping' + #13#10);
p := PAnsiChar(s);
len := Length(s);
repeat
sent := Socket.SendBuf(p^, len);
if sent = -1 then
being
if WSAGetLastError() <> WSAEWOULDBLOCK then
Break;
// TODO: stop trying after several attempts fail...
Continue;
end;
Inc(p, sent);
Dec(len, sent);
until len = 0;
if len = 0 then
Continue;
except
end;
Socket.Close;
end;
end;