Gunnman писал(а):
Откуда берется CurClientID как высчитывается?Отсюда:
#pas
function TTCPServer._ExecuteAccept (T: TThread): Integer;
var
Connection: TClientConnection;
ClientSocket: TSocket;
Addr: TSockAddr;
AddrLen: Integer;
FDRead: TSocketSet;
TimeVal: TTimeVal;
begin
TimeVal.tv_sec := 2; // Таймаут ожидания соединения - 2 сек
TimeVal.tv_usec := 0;
while (not T.Stopped) and (FSocket <> 0) do
begin
FDRead.Count := 1;
FDRead.Socket := FSocket;
// Ожидаем входящее подключение (поток приостанавливается на таймаут)
case select(0, PFDSet(@FDRead), nil, nil, @TimeVal) of
SOCKET_ERROR:
begin
if not T.Stopped then StopListen;
Break;
end;
0: Continue; // Таймаут
end;
// Получено соединение - обрабатываем
FillChar(Addr, SizeOf(TSockAddr), #0);
AddrLen := SizeOf(TSockAddr);
ClientSocket := accept(FSocket, @Addr, @AddrLen);
if ClientSocket = INVALID_SOCKET then // Возникает в случае сбоя сети или закрытого FSocket
begin
if not T.Stopped then StopListen;
Break;
end;
// Если за время таймаута было получено подключение, а сервер остановлен -
// закрываем подключение (оно автора программы, вероятно, уже не интересует)
if T.Stopped then
begin
shutdown(ClientSocket, SD_BOTH);
closesocket(ClientSocket);
Break;
end;
Connection := TClientConnection.Create;
ConnectionAdd(Connection);
with Connection do
begin
OnDisconnect := _OnDisconnect;
if Assigned(Self.OnErrorSend) then OnErrorSend := _OnErrorSend;
if Assigned(Self.OnProgress) then OnProgress := _OnProgress;
if Assigned(Self.OnReceive) then OnReceive := _OnReceive;
if Assigned(Self.OnSend) then OnSend := _OnSend;
ReceiveDelay := FRecvDelay;
RecvDelaySize := FRecvDelaySz;
AsyncEvents := Self.AsyncEvents;
SetSocket(ClientSocket, Integer(Addr.sin_addr), ntohs(Addr.sin_port));
SendTimeout := Self.SendTimeout;
end;
if not T.Stopped then
begin
if Assigned(OnClientConnect) then
begin
if AsyncEvents <> ASYNC_EVENTS_ALL then
T.Synchronize(_SyncClientConnect, Connection)
else
_SyncClientConnect(nil, Connection);
end;
//В OnClientConnect соединение может быть закрыто, поэтому проверяем на существование
if ConnectionExists(Connection) then Connection.StartReceiving;
end;
end;
end;
Connection := TClientConnection.Create;
Выходит, что в Delphi если создать некий объект, затем уничтожить его, а потом опять создать такой же, он вполне может получить адрес предыдущего. Избежать этого никак нельзя, да и не требуется. Важно то, что в любой момент времени в списке коннектов сервера всегда будут уникальные ID. Просто нужно помнить такую особенность. В схеме все равно нужно выполнять обработку onConnect/onDisconnect. Не могу представить ситуации, где важно, чтобы ID были уникальные. Они предназначены только для сопоставления событий/методов с указанным соединением. Нет соединения, нет с чем и сопоставлять.
А вот возможная ситуация, когда событие приходит из соединения 123, и пока обрабатывается, соединение закрывается и приходит новое соединение с тем же номером 123 и уже ему направляется ответ - это некорректная работа схемы: по отключению первого соединения 123, любая, предназначенная ему работа должна быть отменена. И для следующего 123 начата заново.