Вверх ↑
Ответов: 4628
Рейтинг: 749
#1: 2015-03-11 21:23:25 ЛС | профиль | цитата
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;
А именно, ID есть указатель на созданный здесь объект:
Connection := TClientConnection.Create;

Выходит, что в Delphi если создать некий объект, затем уничтожить его, а потом опять создать такой же, он вполне может получить адрес предыдущего. Избежать этого никак нельзя, да и не требуется. Важно то, что в любой момент времени в списке коннектов сервера всегда будут уникальные ID. Просто нужно помнить такую особенность. В схеме все равно нужно выполнять обработку onConnect/onDisconnect. Не могу представить ситуации, где важно, чтобы ID были уникальные. Они предназначены только для сопоставления событий/методов с указанным соединением. Нет соединения, нет с чем и сопоставлять.

А вот возможная ситуация, когда событие приходит из соединения 123, и пока обрабатывается, соединение закрывается и приходит новое соединение с тем же номером 123 и уже ему направляется ответ - это некорректная работа схемы: по отключению первого соединения 123, любая, предназначенная ему работа должна быть отменена. И для следующего 123 начата заново.
карма: 26

0
файлы: 1hjghjs.jpg [32.3KB] [560]