-
Проблемма следующая: Есть TIdTCPClient на одной форме и TIdTCPServer на другой, устанавливаю подключение, вес в порядке... 1й случай: Клиент шлет серверу сообщения, шлет раз, шлет два.... все гут, делаю дисконнект, коннект, все окей опять шлю и все принимается все нормуль... 2й случай: клиент послал серверу сообщение, сервер его обработал, все гут, потом сервер шлет клиенту сообщение, клиент его принимает... все казалось бы Ок, но если после того, как сервер отправляет сообщение клиенту, и потом я делаю клиенту дисконнект, то ничё больше не работает, делаю клиентом повторный коннект, он пишет типа подсоединился, но сообщения больше не обрабатываются на сервере и сам сервер не может ниче послать грит ошибка "Connection Closed Grasfully" и все... как это решить... Помогите плиииз... P.S. использую Delphi 7 и Indy 10.1.5, отправка сообщений: Клиент: IdTCPClient1.Socket.WriteLn Сервер:TIdContext(IdTCPServer1.Contexts.LockList.Items[0]).Connection.Socket.Wri teLn
-
Кстати всем превет! Заранее спс...
-
У тебя ошибка в программе.
-
ВОт так обрабатываю сообщения на сервере:
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext); var recvfs: TFileStream; i, cp : byte; tmsg : TPackage; Buf : TIdBytes; begin tmsg.fHeader.totalSize := StrToInt64(AContext.Connection.Socket.ReadLn); AContext.Connection.Socket.ReadBytes( Buf , tmsg.fHeader.totalSize ); ZeroMemory(@tmsg,sizeof(tmsg)); tmsg.fHeader.cmd := Buf[0]; tmsg.fHeader.ParamCount := Buf[1];
Move ( Buf[2] , Cardinal(tmsg.fHeader.totalSize) , sizeof(cardinal) );
SetLength(tmsg.fHeader.ParamsLength , tmsg.fHeader.ParamCount); if tmsg.fHeader.ParamCount > 0 then Move( Buf[2 + SizeOf(cardinal)] , tmsg.fHeader.ParamsLength[0] , tmsg.fHeader.ParamCount * SizeOf(Cardinal) );
SetLength( tmsg.fData.Params , tmsg.fHeader.ParamCount ); if tmsg.fHeader.ParamCount > 0 then begin SetLength( tmsg.fData.Params[0] , tmsg.fHeader.Paramslength[0] ); cp := 2 + SizeOf(cardinal) + tmsg.fHeader.ParamCount * Sizeof(cardinal); Move( Buf[cp] , tmsg.fData.Params[0][1] , tmsg.fHeader.Paramslength[0] ); for i := 1 to tmsg.fHeader.ParamCount - 1 do begin inc( cp , tmsg.fHeader.Paramslength[i - 1] ); SetLength( tmsg.fData.Params[i] , tmsg.fHeader.Paramslength[i] ); Move( Buf[cp] , tmsg.fData.Params[i][1] , tmsg.fHeader.Paramslength[i] ); end; end; Memo1.Lines.Add('*********** We have a new message*******'); Memo1.Lines.Add(' Message CMD Code = ' + IntToStr(tmsg.fHeader.cmd)); Memo1.Lines.Add(' Message Params: ');
if tmsg.fHeader.paramCount>0 then for i := 0 to tmsg.fHeader.ParamCount - 1 do Memo1.Lines.Add(' ' + (tmsg.fData.Params[i])); Case tmsg.fHeader.cmd of CMD_CONNECTION_STR : Memo1.Lines.Add('We have a new connection...'); CMD_MESSAGE : Memo1.Lines.Add('This is a message'); CMD_FILE_UPLOAD :begin recvfs:= TFileStream.Create(ExtractFileName(tmsg.fData.Params[0])+'.tmp',fmCreate); AContext.Connection.Socket.ReadStream(recvfs,StrToInt(tmsg.fData.Params[1]),fals e); Memo1.Lines.Add('-----> New File upload complete...'); end; { CMD_DISCONNECT:begin AContext.Connection.Disconnect; end; {} end;
Memo1.Lines.Add('*********** End of new message*******'); end;
TPackageHeader = record cmd : byte; ParamCount : byte; totalSize : cardinal; ParamsLength : array of cardinal; end;
TPackageData = record Params:array of string; end;
TPackage = record fHeader : TPackageHeader; fData : TPackageData; end;
Сообщения сервер отправляет так: procedure TForm1.SendPackage(pcmd, pparamCount: byte; pparams: array of string); var tmsg : TPackage; i : integer; buf : TIdBytes; begin // // buf:=@tmsg; ZeroMemory(@tmsg,sizeof(tmsg)); tmsg.fHeader.cmd := pcmd; // tmsg.fHeader.totalSize := sizeof(tmsg.fHeader.cmd);
tmsg.fHeader.ParamCount := pparamCount; // tmsg.fHeader.totalSize := tmsg.fHeader.totalSize + sizeof(tmsg.fHeader.ParamCount);
// tmsg.fHeader.totalSize := tmsg.fHeader.totalSize + sizeof(tmsg.fHeader.totalSize);
SetLength(tmsg.fHeader.ParamsLength,pparamCount); // tmsg.fHeader.totalSize := tmsg.fHeader.totalSize + length(tmsg.fHeader.ParamsLength)*Sizeof(cardinal); SetLength(tmsg.fData.Params,pparamCount);
for i := 0 to pparamCount-1 do begin SetLength(tmsg.fData.Params[i],length(pparams[i])); Move(pparams[i][1],tmsg.fData.Params[i][1], length(pparams[i])); tmsg.fHeader.ParamsLength[i]:= length(tmsg.fData.Params[i]); tmsg.fHeader.totalSize:= tmsg.fHeader.totalSize + length(tmsg.fData.Params[i]) ; end;
tmsg.fHeader.totalSize := tmsg.fHeader.totalSize+ Sizeof(tmsg.fHeader.cmd)+ Sizeof(tmsg.fHeader.totalSize)+ Sizeof(tmsg.fHeader.ParamCount)+ Length(tmsg.fHeader.ParamsLength)*SizeOf(Cardinal);
SetLength(Buf, tmsg.fHeader.totalSize); Move(tmsg.fHeader.cmd, buf[0], 1); Move(tmsg.fHeader.ParamCount, buf[1], 1); Move(cardinal(tmsg.fHeader.totalSize), buf[2], sizeof(cardinal));
if pparamCount>0 then for i := 0 to pparamCount-1 do Move(tmsg.fHeader.ParamsLength[i], buf[6+i*Sizeof(Cardinal)], SizeOf(Cardinal));
if pparamCount>0 then begin Move(tmsg.fData.Params[0][1], buf[6+pParamCount*Sizeof(Cardinal)], length(tmsg.fData.Params[0])); for i := 1 to pparamCount-1 do Move(tmsg.fData.Params[i][1], buf[6+pParamCount*Sizeof(Cardinal)+Length(tmsg.fData.Params[i-1])], length(tmsg.fData.Params[i])); end; TIdContext(IdTCPServer1.Contexts.LockList.Items[0]).Connection.Socket.WriteLn(In tToStr(tmsg.fHeader.totalSize)); TIdContext(IdTCPServer1.Contexts.LockList.Items[0]).Connection.Socket.Write(Buf) ; end;
-
У клиента почти таже бадяга, но тока сообщения обрабатываются в таймере(как показано в Demosах):
procedure TForm1.Timer1Timer(Sender: TObject); var i:integer; s:string; begin if not IdTCPClient1.Connected then exit;
i:=IdTCPClient1.IOHandler.InputBuffer.Size; if i>0 then GetNewMessages; end;
GetNewMessages почти тот же код, что и у procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
-
Очевидных безобразий ы твоем коде явно не одно.
Взять хотя бы это:
> ZeroMemory(@tmsg,sizeof(tmsg));
С учетом типа поля Params:array of string обнуление этого поля недопустимо.
-
Ну про эту строчку вообще забыть можно... она сути проблеммы не меняет... Заменим её на tmsg.fHeader.cmd:=0; tmsg.fHeader.ParamCount:=0; tmsg.fHeader.totalSize:=0;
-
Воспользуйся встроенным отладчиком.
-
Я пользовался уже вчера им весь день, Buf заполняется идеально, tmsg заполняется идеально, дошел до самых низов Indy т.сказать все идеально, кол-во отправленных байт идеально, я уже от безысходности тут пишу, никогда нигде не отписывал... Если хочешь я тебе на мыло пришлю исходники, сам протестишь...???
-
> Если хочешь
Не хочу. Оно мне надо ?)
Факт-то налицо - отказ с диагностикой Connection Closed Grasfully возникает когда партнер по соединению закрывает его со своей стороны по своей же инициативе.
-
Праааально гришь, эта ошибка вылетает у TIdTCPServer значит клиент разорвал соединение, чтож все верно, но почиму она возникает только после того, как я с сервера пошлю клиенту сообщение???
Если Сервер ничего не посылает за сеанс клиенту, то клиент может коннектится и дисконнектится, и передавать серверу сообщения скока угодно раз... А стоит клиенту подключиться, серверу отправить сообщение, клиенту отключиться, клиенту подключиться, как УСЁ "Кирдык".... в чем прикол та??
-
> в чем прикол та?
Сказал ведь уже - у тебя ошибка в программе. Судя по [10] - в программе клиента.
-
Может я дисконнект у клиента неправильно делаю, может там что-ть ещё очищать надо?? ну эт савсем нонсенс был бы....
-
> PonosetcDM © (17.06.10 12:35) [12]
Таймер-то на стороне клиента нафих понадобился ?)
-
чтобы обрабатывать приход сообщений от сервера... можно и в отдельном потоке тоже самое делать, суть от этого не поменяется...
-
Клиент с сервером должен взаимодействовать по схеме "послал запрос - дождался и получил ответ на этот запрос"
Не вижу чтобы твой сервер в обработчике OnExecute посылал ответы клиенту на его запросы, хотя он обязан делать это именно там и нигде иначе.
-
Интересно, а если у меня на сервере произошло какое, то изменение, и я хачу сообщить об этом клиенту, чмне что прикажешь ждать, пока клиент не спросит у сервера, типа "все ли у тя в порядке?"... это же не прально... я бы хател сам уведомлять подключившихся клиентов о том что у мя что-то не так...чего я не магу сделать в OnExecute => должен быть способ это сделать...))
-
> чего я не магу сделать в OnExecute
Сделать это в OnExecute тебе запрещает религия ?
> а если у меня на сервере произошло какое, то изменение, > и я хачу сообщить об этом клиенту, чмне что прикажешь ждать, > пока клиент не спросит у сервера, типа "все ли у тя в порядке? > "
1. К. делает запрос "Сервер, я жду изменений" 2. С. отвечает на запрос "Нет изменений". 3. goto 1
или
1. К. делает запрос "Сервер, я жду изменений" 2. С. отвечает на запрос "На тебе изменеия". 3. К. получает и обрабатывает изменения . 4. goto 1
Именно по этим сценариям ты взаимодейстуешь прямо сейчас с delphimaster.ru-сервером и нос почему-то не воротишь)
-
Хорошо, пример такой: на сервере ясмотрю картинки, а на клиенте хачу чтобы мне приходило имя файла этой картинки.... Исходя из [17] выходит, что клиент должен постоянно опрашивать сервер, и получать от него это имя файла, и когда будет просматриваться другая картинка, я и получу это "другое" имя файла...
Но ведь по моему логичнее было бы просто при открытии очередной картинки сервером, посылать имя файла этой "другой" картинки клиенту...
-
> клиент должен постоянно опрашивать сервер
Для подавляющего большинства распределенных приложений это абсолютно нормальная и вполне оправданная логика.
-
А как же быть с тем меньшинством???? Для которых эта "абсолютно нормальная логика" не одходит. Я не говорю, что мой проэкт не подходит под поняти "подавляющее большинство распределённых приложений", но просто интересно как быть...??
-
Протокол инф.обмена должен соответствовать этой логике "меньшинства". Ну и, разумеется, реализация этого протокола должна быть соответствующей.
-
> PonosetcDM (17.06.2010 15:15:16) [16]
А ты сервер или спамер. Но ты имеешь право посылать сообщения подсоединившимся к тебе пользователям, если они готовы слушать тебя.
-
> PonosetcDM (17.06.2010 15:37:18) [18]
Постоянно опрашивать не надо, а надо ждать сообщения от сервера, как поступит так и обрабатывай. После установки соединения между сервером и клиентом нет разницы, они равноправны. Смотри методы и свойства TIdTCPServer и твоего клиента.
-
Anatoly Podgoretsky © (17.06.10 15:58) [23] Я не знаю прочитали вы полностью нашу с Сергеем переписку или нет, пэтому уточню суть проблеммы: Есть приложение с TIdTCPServer(сервер) и приложение с TIdTCPClient(клиент). 1. я делаю клиентом коннект к серверу IdTCPClient1.Connect; все хорошо, все подлючается, все работает. 2. я отправляю сообщение клиентом, серверу, он(сервер) обрабатывает его. все хорошо, все принято и обработано, все работает. 3. я посылаю сообщение сервером, клиенту, он(клиент) обрабатывает его. все хорошо, все принято и обработано, все работает.
Шаги 2 и 3 выполнять можно скока ХОШЬ....
4. делаю клиентом дисконнект. все дисконнектится все нормально... 5. делаю коннект, а вот тут "пффууук...." клиент грит, что он подконнектился, а сервер не реагирует, и ри попытке отправить сервером сообщение клиенту происходит "Connection Closed Grasfully"..., а при попытке повторного коннекта(без Disconnect), клиент говорит Already connected.. т.е. он считает, что он уже подключен...
-
> PonosetcDM (17.06.2010 16:24:24) [24]
Я как раз прочитал и ответил. После коннекта установлены двухсторонние отношения и клиент и сервер равноправны. Опрашивать ничего не надо, надо ждать сообщения в отдельном потоке конечно с использованием WaitForSingleObject
-
> PonosetcDM © (17.06.10 16:24) [24]
Ты так и не объяснил какая религия и почему запрещает тебе передавать данные клиенту непосредственнов в OnExecute
-
> PonosetcDM (17.06.2010 16:24:24) [24]
В ICS и это делать не надо, достаточно написать обработчик OnReceive, поток нужен для Инди. Но это моменты реализации.
-
Воооо.... ваще чума.... я запустил программу(сервер) подключился к ней по telnet из cmd, сервак послал клиенту сообщение, все окей, принято telnet'ом, обработано... закрываю telnet, открываю telnet, делаю коннект "типа все окей", сервак шлет сообщение клиенту и....... правильно "Connection Closed Grasfully"... ваще жуть...
-
> ваще чума
> ваще жуть
А скажи, любезный, вот ты заблокировал список Contexts, а разблокировать его за тебя кто будет, Пушкин ?
Ведь не ты один этим списком пользуешься - им еще и TIdCustomTCPServer пользуется, причем в 1-ю очередь !
При обработке событий коннекта/дисконнекта IdCustomTCPServer обращается к этому списку, выполняя попытку заблокировать его для внесения соотв.изменения, например, для удаления Item[0] после дисконнекта 1-го клиента и вновь создания Item[0] при коннекте ..
А ты взял и уселся на него верхом, не пуская никого покататься)
Вот тебе и грабли)
-
1. протокол - говно ты где видал что сначала идет список длинн, потом список данных (табличное представление не в счет) общепринято: длинна-значание, длинна-значение
2. описание структур - говно, дублирующие поля totalSize и ParamsLength в итоге потенциальное переполнение буфера когда totalSize<>Sum(ParamsLength)
3. работа с памятью - говно (cp := 2 + SizeOf(cardinal) + tmsg.fHeader.ParamCount * Sizeof(cardinal);)
4. работа с потоками - говно, общение с VCL в потоке (Memo1.Lines.Add)
это только про сервер... про клиента: таймер убил меня, читать дальше нет мочи
-
вот сравни с [3]procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
tmsg : TPackage;
i: byte;
recvfs: TFileStream;
MemoLines:string;
begin
with AContext.Connection.Socket,tmsg.fHeader,tmsg.fData do
begin
totalSize :=StrToInt64(ReadLn); cmd:=ReadByte;
ParamCount := ReadByte;
SetLength(ParamsLength,ParamCount);
for i:=0 to ParamCount-1 do
ParamsLength[i]:=ReadLongInt(false);
SetLength(Params,ParamCount);
for i:=0 to ParamCount-1 do
Params[i]:=ReadString(ParamsLength[i],enDefault);
MemoLines:='';
MemoLines:=MemoLines+'*********** We have a new message*******'+#13#10;
MemoLines:=MemoLines+' Message CMD Code = '+ IntToStr(tmsg.fHeader.cmd)+#13#10;
MemoLines:=MemoLines+' Message Params: '+#13#10;
for i:=0 to ParamCount-1 do
MemoLines:=MemoLines+' ' + (Params[i])+#13#10;
Case cmd of
1 : MemoLines:=MemoLines+'We have a new connection...'+#13#10;
2 : MemoLines:=MemoLines+'This is a message'+#13#10;
3 : begin
recvfs:= TFileStream.Create(ExtractFileName(Params[0])+'.tmp',fmCreate);
try
ReadStream(recvfs,StrToInt(Params[1]),false);
finally
recvfs.Free;
end;
MemoLines:=MemoLines+'-----> New File upload complete...'+#13#10;
end;
end;
end;
MemoLines:=MemoLines+'*********** End of new message*******'+#13#10;
end;
-
> делаю коннект "типа все окей", сервак шлет сообщение клиенту > и....... > правильно "Connection Closed Grasfully"... ваще жуть.. > .
Претензии к реализации сервера, невероятно кривая.
-
> Anatoly Podgoretsky © (18.06.10 10:31) [32]
Какая бы ни была кривая, но UnlockList-то надо вызывать)
-
procedure TForm1.SendPackage(pcmd, pparamCount: byte;
pparams: array of string);
var
tmsg:TPackage;
buf:TMemoryStream;
List:TList;
i:integer;
begin
buf:=TMemoryStream.Create;
try
with tmsg.fHeader,tmsg.fData do
begin
cmd:= pcmd;
ParamCount := pparamCount;
SetLength(ParamsLength,ParamCount);
SetLength(Params,ParamCount);
for i:=0 to ParamCount-1 do
begin
Params[i]:=pparams[i];
ParamsLength[i]:=length(Params[i]);
end;
buf.WriteBuffer(cmd,SizeOf(cmd));
buf.WriteBuffer(ParamCount,SizeOf(ParamCount));
for i:=0 to ParamCount-1 do
buf.WriteBuffer(ParamsLength[i],SizeOf(cardinal));
for i:=0 to ParamCount-1 do
buf.WriteBuffer(PChar(Params[i])^,ParamsLength[i]);
end;
List:=IdTCPServer1.Contexts.LockList;
try
for i:=0 to List.Count-1 do
with TIdContext(List.Items[i]).Connection.Socket do
begin
WriteLn(IntToStr(buf.Size));
Write(buf);
end;
finally
IdTCPServer1.Contexts.UnlockList; end;
finally
buf.Free; end;
end;
-
ЗАБЫЛ добавить: как только выходим из IdTCPServer1Execute - финиталякомедия конекшен рвется, так что переделывай в все в одном IdTCPServer1Execute или как то усыпляй IdTCPServer1Execute...
-
> Сергей М. (18.06.2010 10:34:33) [33]
Это часть кривизны.
-
Блин я согласен все замечания хороши, базара ноль... да вот проблемма остается актуальной.. на форме компоненты TIdTCPServer, TMemo и ТБатон вот код куда уж проще то...
unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer, IdContext, StdCtrls, Buttons;
type TForm1 = class(TForm) IdTCPServer1: TIdTCPServer; Memo1: TMemo; BitBtn1: TBitBtn; procedure IdTCPServer1Execute(AContext: TIdContext); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure BitBtn1Click(Sender: TObject); procedure IdTCPServer1Connect(AContext: TIdContext); procedure IdTCPServer1Disconnect(AContext: TIdContext); private { Private declarations } public { Public declarations } end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext); var s:string; begin s:=AContext.Connection.IOHandler.ReadLn; Memo1.Lines.Add(s); end;
procedure TForm1.FormCreate(Sender: TObject); begin IdTCPServer1.Active:=true; end;
procedure TForm1.FormDestroy(Sender: TObject); begin IdTCPServer1.Active:=false; end;
procedure TForm1.BitBtn1Click(Sender: TObject); var i:integer; begin try for i:=0 to IdTCPServer1.Contexts.LockList.Count-1 do with TIdContext(IdTCPServer1.Contexts.LockList.Items[i]).Connection.Socket do WriteLn('123'); finally IdTCPServer1.Contexts.UnlockList; end; end;
procedure TForm1.IdTCPServer1Connect(AContext: TIdContext); begin Memo1.Lines.Add('we have a new connection') end;
procedure TForm1.IdTCPServer1Disconnect(AContext: TIdContext); begin Memo1.Lines.Add('Client disconnected'); end;
end.
иииииииии............ все теже грабли...
Запускаю эту прогу, запускаю телнет коннект телнета "o localhost 12312" нажимаю на батон, в окне телнета появляется "123", нажимаю на батон ищё раз, в окне телнета появляется ищё "123", закрываю телнет, срабатывает дисконнект запускаю телнет опять, прога при этом не перезапускалась(естественно)... делаю телнетом "o localhost 12312", и даже коннект у сервера не срабатывает.... все по шагам разжевал....
-
> все теже грабли
Ну где-же "теже" ? Connection closed gracefully как рукой сняло)
И, кстати, ты в [35] вник ?
-
Нууу не знаю что у Вас сняло, у мя как было так и осталось, какая у Вас версия Indy????
Про [35] хзхз, почиму это коннекшен рвется????
и что за усыпляй???
у мя когда клиент коннект сделал, заходит в и IdTCPServer1Execute(AContext: TIdContext); останавливается на AContext.Connection.IOHandler.ReadLn, пока не придет что-ть.
-
> PonosetcDM (18.06.2010 11:48:37) [37]
Это же потоки, откуда Memo1.Lines.Add без синхронизации.
-
> почиму это коннекшен рвется?
Потому что как только клиент отправит какую-либо строку, ReadLn тут же вернет управление, и после лажи [40] Execute завершит выполнение, что ведет к разрыву соединения по инициативе сервера
-
> Это же потоки, откуда Memo1.Lines.Add без синхронизации.
Окей, давай эту строчку ваще уберём.... и все равно T = Telnet S = Server Project
запустил Т запустил S T, o localhost 12312 S принял подключение S отправил "123", T обработал и выдал "123" T закрыли, Т открыли T, o localhost 12312 S при посылке грит Connection closed gracefully
теперь ваще все Гут должно быть, никакой проблеммы с синхронизацией... и все тоже самое...
-
> PonosetcDM © (18.06.10 12:48) [42]
> запускаю телнет опять, > делаю телнетом "o localhost 12312", и даже коннект у сервера > не срабатывае
Зачем же давить BitBtn1, если нет ни одного коннекта ?)
-
Хм.... ТОгда вопрос: А почиму его нет))????? Ведь когда телнет дисконектился, у сервера сработал дисконнект, а потом коннект не срабатывает...
-
PonosetcDM © (18.06.10 11:48) [37] for i:=0 to IdTCPServer1.Contexts.LockList.Count-1 do чтож ты делаешь то? нехороший человек
-
procedure TForm1.BitBtn1Click(Sender: TObject); var i:integer; list:TList; begin list:=IdTCPServer1.Contexts.LockList; try for i:=0 to list.Count-1 do with TIdContext(list.Items[i]).Connection.Socket do WriteLn('123'); finally IdTCPServer1.Contexts.UnlockList; end; end;
-
Сергей М. © (18.06.10 12:44) [41] +1 к [35]
-
Мдааа......... вот так таааааакккк...... Спс большое вроде бы все работает, теперь буду следить за всем, и закреплю в аналах своей памяти все посты сказанные сдесь...
Только хотелось бы узнать по-подробнее: почиму не работает с for i:=0 to IdTCPServer1.Contexts.LockList.Count-1 do, а если IdTCPServer1.Contexts.LockList.Count-1 переопределить, то все работает??
СПС всем огромное...
-
сдесь = здесь
-
> в аналах своей памяти
Анальная у тебя память, однако))))
-
PonosetcDM © (18.06.10 14:39) [48] количество LockList дожно быть равно колву UnlockList тут PonosetcDM © (18.06.10 11:48) [37] procedure TForm1.BitBtn1Click(Sender: TObject); var i:integer; begin try for i:=0 to IdTCPServer1.Contexts.LockList.Count-1 do with TIdContext(IdTCPServer1.Contexts.LockList.Items[i]).Connection.Socket do WriteLn('123'); finally IdTCPServer1.Contexts.UnlockList; end; end;
Колво LockList = 1+ListCount и это при условии что дельфи за тебя оптимизирует i:=0 to IdTCPServer1.Contexts.LockList.Count-1 за менив постоянное вычисление предела цикла на единичное вычисление
колво UnlockList = 1
-
> Slym (20.06.2010 13:05:51) [51]
А ты можешь документально подтвердить постоянное вычисление предела цикла?
-
> Slym © (20.06.10 13:05) [51] > количество LockList дожно быть равно колву UnlockList
Это же не семафор)
-
Сергей М. © (20.06.10 22:30) [53] а критической секции это не касается? один поток накрутит EnterCriticalSection и пока не скрутит столько же раз Leave - другие будут ждать Anatoly Podgoretsky © (20.06.10 13:19) [52] читать отрывочно умеешь, теперь прочитай еще раз полностью: вникни в формулу (1 (вычисление предела)+ListCount (кол-во итераций)) и дочитай про оптимизацию
-
ТЫ локлист открыл и заблокировал,разблокируй его и все пойдет
|