Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2004.04.11;
Скачать: [xml.tar.bz2];

Вниз

TIdTCPServer + несколько клиентов.   Найти похожие ветки 

 
Gym ©   (2004-03-07 16:31) [0]

Здравствуйте уважаемые мастера.
Подскажите, пожалуйста, как в TIdTCPServer узнать ip и порт, с которого подключился клиент, количество подключённых клиентов. Как отослать каждому клиенту, допустим, текстовую строку.
Спасибо.


 
Gym ©   (2004-03-07 16:31) [0]

Здравствуйте уважаемые мастера.
Подскажите, пожалуйста, как в TIdTCPServer узнать ip и порт, с которого подключился клиент, количество подключённых клиентов. Как отослать каждому клиенту, допустим, текстовую строку.
Спасибо.


 
S@shka ©   (2004-03-07 22:19) [1]

athread.connection.binding.peerip


 
S@shka ©   (2004-03-07 22:19) [1]

athread.connection.binding.peerip


 
Gym ©   (2004-03-08 06:02) [2]


> S@shka ©   (07.03.04 22:19) [1]
> athread.connection.binding.peerip

Так я получу только ip клиента.
Но главное я не знаю как перебрать всех клиентов приконекченных к серверу и послать им какие-либо данные. Неужели никто не знает, как это делается? Что никто  не писал клиент-серверных приложений, где к серверу подключается больше чем один клиент?
Не сочтите за труд, ответьте пожалуйста.


 
Gym ©   (2004-03-08 06:02) [2]


> S@shka ©   (07.03.04 22:19) [1]
> athread.connection.binding.peerip

Так я получу только ip клиента.
Но главное я не знаю как перебрать всех клиентов приконекченных к серверу и послать им какие-либо данные. Неужели никто не знает, как это делается? Что никто  не писал клиент-серверных приложений, где к серверу подключается больше чем один клиент?
Не сочтите за труд, ответьте пожалуйста.


 
Gym ©   (2004-03-08 15:47) [3]

Я тут кое-что придумал:

procedure TfmServer.TCPServerConnect(AThread: TIdPeerThread);
begin
 MThreads[i]:=TIdPeerThread.Create;
 MThreads[i]:=AThread;
 mmLog.Lines.Add(MThreads[i].Connection.Socket.Binding.PeerIP);
 i:=i+1;
end;

procedure TfmServer.Button1Click(Sender: TObject);
var
 n : integer;
begin
 for n:=0 to i-1 do MThreads[n].Connection.Writeln(IntToStr(n));
end;


Если вместо массивов использовать TList то должно получиться сносно,
но придётся следить за каждым клиентом, если он дисконектился находить
и удалять его из списка и т.д.
Должно же быть что-то похожее в самом компоненте? Если кто знает подскажите.


 
Gym ©   (2004-03-08 15:47) [3]

Я тут кое-что придумал:

procedure TfmServer.TCPServerConnect(AThread: TIdPeerThread);
begin
 MThreads[i]:=TIdPeerThread.Create;
 MThreads[i]:=AThread;
 mmLog.Lines.Add(MThreads[i].Connection.Socket.Binding.PeerIP);
 i:=i+1;
end;

procedure TfmServer.Button1Click(Sender: TObject);
var
 n : integer;
begin
 for n:=0 to i-1 do MThreads[n].Connection.Writeln(IntToStr(n));
end;


Если вместо массивов использовать TList то должно получиться сносно,
но придётся следить за каждым клиентом, если он дисконектился находить
и удалять его из списка и т.д.
Должно же быть что-то похожее в самом компоненте? Если кто знает подскажите.


 
Gym ©   (2004-03-09 14:51) [4]

Удалено модератором
Примечание: Создание пустых сообщений ...


 
Gym ©   (2004-03-09 14:51) [4]

Удалено модератором
Примечание: Создание пустых сообщений ...


 
Reindeer Moss Eater ©   (2004-03-09 14:59) [5]

Чем родной-то список созданных клиентских ниток не устраивает?


 
Reindeer Moss Eater ©   (2004-03-09 14:59) [5]

Чем родной-то список созданных клиентских ниток не устраивает?


 
Gym ©   (2004-03-09 19:15) [6]


> Reindeer Moss Eater ©   (09.03.04 14:59) [5]
> Чем родной-то список созданных клиентских ниток не устраивает?


Ну во превых тем что я не знаю где он. :)Подскажите
пожалуйста.
А во вторых я хочу хранить вместе со списком следующие поля:  

RAcount = record
   Thread  : TIdPeerThread;
   Name    : string;
   Pwd     : string;
end;

Что бы можно было сопоставить ID потока с ником и паролем.


 
Gym ©   (2004-03-09 19:15) [6]


> Reindeer Moss Eater ©   (09.03.04 14:59) [5]
> Чем родной-то список созданных клиентских ниток не устраивает?


Ну во превых тем что я не знаю где он. :)Подскажите
пожалуйста.
А во вторых я хочу хранить вместе со списком следующие поля:  

RAcount = record
   Thread  : TIdPeerThread;
   Name    : string;
   Pwd     : string;
end;

Что бы можно было сопоставить ID потока с ником и паролем.


 
S@shka ©   (2004-03-09 21:39) [7]

Это находиться в папке
Delphi6\Demos\Chat - то что тебе нужно на Indy :)


 
S@shka ©   (2004-03-09 21:39) [7]

Это находиться в папке
Delphi6\Demos\Chat - то что тебе нужно на Indy :)


 
Reindeer Moss Eater ©   (2004-03-09 22:18) [8]

Ну во превых тем что я не знаю где он. :)Подскажите
пожалуйста.


TIdTCPServer.Threads

А во вторых я хочу хранить вместе со списком следующие поля:  

RAcount = record
  Thread  : TIdPeerThread;
  Name    : string;
  Pwd     : string;
end;


var
MyData : RAcount;

TidPeerThread.Data := TObject(@MyData);


 
Reindeer Moss Eater ©   (2004-03-09 22:18) [8]

Ну во превых тем что я не знаю где он. :)Подскажите
пожалуйста.


TIdTCPServer.Threads

А во вторых я хочу хранить вместе со списком следующие поля:  

RAcount = record
  Thread  : TIdPeerThread;
  Name    : string;
  Pwd     : string;
end;


var
MyData : RAcount;

TidPeerThread.Data := TObject(@MyData);


 
Gym ©   (2004-03-10 08:53) [9]

to Reindeer Moss Eater

Спасибо за ответ но,
Укажите, пожалуйста, в каком месте программы  нужно вставлять строку:

TidPeerThread.Data := TObject(@MyData);

И как потом обращаться к полям MyData.Name и MyData.Pwd?
А то у меня что-то ничего не получилось.

unit ServUnit;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, IdAntiFreezeBase, IdAntiFreeze, IdBaseComponent, IdComponent,
 IdTCPServer, StdCtrls;

type

 RAcount = record
   Name    : string;
   Pwd     : string;
 end;

 TForm1 = class(TForm)
   Memo1: TMemo;
   Button1: TButton;
   IdTCPServer1: TIdTCPServer;
   IdAntiFreeze1: TIdAntiFreeze;
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure IdTCPServer1Connect(AThread: TIdPeerThread);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1  : TForm1;
 MyData : RAcount;
implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
 idTCPServer1.Active:=True;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 idTCPServer1.Active:=False;
end;

procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
var
 ThrList : TList;
begin
 Memo1.Lines.Add(AThread.Connection.Socket.Binding.PeerIP);
 Memo1.Lines.Add(IntToStr(AThread.ThreadID));
end;

end.


 
Gym ©   (2004-03-10 08:53) [9]

to Reindeer Moss Eater

Спасибо за ответ но,
Укажите, пожалуйста, в каком месте программы  нужно вставлять строку:

TidPeerThread.Data := TObject(@MyData);

И как потом обращаться к полям MyData.Name и MyData.Pwd?
А то у меня что-то ничего не получилось.

unit ServUnit;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, IdAntiFreezeBase, IdAntiFreeze, IdBaseComponent, IdComponent,
 IdTCPServer, StdCtrls;

type

 RAcount = record
   Name    : string;
   Pwd     : string;
 end;

 TForm1 = class(TForm)
   Memo1: TMemo;
   Button1: TButton;
   IdTCPServer1: TIdTCPServer;
   IdAntiFreeze1: TIdAntiFreeze;
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure IdTCPServer1Connect(AThread: TIdPeerThread);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1  : TForm1;
 MyData : RAcount;
implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
 idTCPServer1.Active:=True;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 idTCPServer1.Active:=False;
end;

procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
var
 ThrList : TList;
begin
 Memo1.Lines.Add(AThread.Connection.Socket.Binding.PeerIP);
 Memo1.Lines.Add(IntToStr(AThread.ThreadID));
end;

end.


 
Reindeer Moss Eater ©   (2004-03-10 09:00) [10]

Спасибо за ответ но,
Укажите, пожалуйста, в каком месте программы  нужно вставлять строку:

TidPeerThread.Data := TObject(@MyData);


Во второй строчке сверху.

И как потом обращаться к полям MyData.Name и MyData.Pwd?
А то у меня что-то ничего не получилось.


Обычное приведение типов.
Нужно привести TObject к типу указателя на RAcount


 
Reindeer Moss Eater ©   (2004-03-10 09:00) [10]

Спасибо за ответ но,
Укажите, пожалуйста, в каком месте программы  нужно вставлять строку:

TidPeerThread.Data := TObject(@MyData);


Во второй строчке сверху.

И как потом обращаться к полям MyData.Name и MyData.Pwd?
А то у меня что-то ничего не получилось.


Обычное приведение типов.
Нужно привести TObject к типу указателя на RAcount


 
Gym ©   (2004-03-10 19:06) [11]


> Во второй строчке сверху.

Это в обработчик TForm1.FormCreate что-ли?


> Обычное приведение типов.
> Нужно привести TObject к типу указателя на RAcount


Дело в том, что у меня не слишком богатый опыт в этом
самом приведении типов, а так же в наследованиях всяких
и полиморфизмах. Не мог бы ты, что называется "на пальцах",
как для новичка, показать всё на примере. Я не прошу писать
и компилировать пример. Просто возми за основу листинг выложенный выше и расставь что где нужно (если не затруднит).
Спасибо.


 
Gym ©   (2004-03-10 19:06) [11]


> Во второй строчке сверху.

Это в обработчик TForm1.FormCreate что-ли?


> Обычное приведение типов.
> Нужно привести TObject к типу указателя на RAcount


Дело в том, что у меня не слишком богатый опыт в этом
самом приведении типов, а так же в наследованиях всяких
и полиморфизмах. Не мог бы ты, что называется "на пальцах",
как для новичка, показать всё на примере. Я не прошу писать
и компилировать пример. Просто возми за основу листинг выложенный выше и расставь что где нужно (если не затруднит).
Спасибо.


 
Reindeer Moss Eater ©   (2004-03-11 09:31) [12]

Класс TidPeerThread.
У класса есть свойство Data : TObject.
В нем можно хранить указатель на TObject.
А можно и не хранить указатель на TObject, а хранить указатель на что душе угодно.
Например на твою record

PMyRecord = ^TMyRecord;
TMyRecord = record
MyName : string;
end;

var MyRec : TMyRecord;

AThread.Data := @MyRec;

Про вторую строчку сверху - то была шутка.
"Куда это вставлять" - решай сам. Определись когда тебе уже пора с клиентским подключением связывать свою структуру данных, туда и вставляй.

Обратное преобразование:

ShowMessage("Поле MyName в записи TMyRecord имеет значение:" + PMyRecord(AThread.Data)^.MyName);


 
Reindeer Moss Eater ©   (2004-03-11 09:31) [12]

Класс TidPeerThread.
У класса есть свойство Data : TObject.
В нем можно хранить указатель на TObject.
А можно и не хранить указатель на TObject, а хранить указатель на что душе угодно.
Например на твою record

PMyRecord = ^TMyRecord;
TMyRecord = record
MyName : string;
end;

var MyRec : TMyRecord;

AThread.Data := @MyRec;

Про вторую строчку сверху - то была шутка.
"Куда это вставлять" - решай сам. Определись когда тебе уже пора с клиентским подключением связывать свою структуру данных, туда и вставляй.

Обратное преобразование:

ShowMessage("Поле MyName в записи TMyRecord имеет значение:" + PMyRecord(AThread.Data)^.MyName);


 
Gym ©   (2004-03-11 15:33) [13]

to Reindeer Moss Eater

Да я уж понял что шутка. Правда сначала долго ломал голову, над тем, что ты имеешь в виду. :)))

Теперь о деле. С тем как в Data засунуть свою запись я вроде разобрался. Теперь как её оттуда вытащить.

ShowMessage("Поле MyName в записи TMyRecord имеет значение:" + PMyRecord(AThread.Data)^.MyName);

это подходит если я хочу обратиться из той же процедуры в которой
вводил данные например из procedure TfmServer.TCPServerConnect(AThread: TIdPeerThread);

А если мне нужно читать данные допустим по нажатию кнопки?
Я тут попробовал кое-что, но видно не правильно. Посмотри пожалуйста что не так.

type
 PThread = ^TIdPeerThread;
 PData = ^RDAta;
 ...

var
 CliData      : RData;
 ...

procedure TfmServer.TCPServerConnect(AThread: TIdPeerThread);
begin
 AThread.Data:=@CliData;
 PData(AThread.Data)^.Name:=("Name"+IntToStr(AllConection));
 ...
 AllConection:=AllConection+1;
end;

procedure TfmServer.Button1Click(Sender: TObject);
begin
mmLog.Lines.Add(PData(PThread(TCPServer.Threads.LockList.Items[0])^.Data)^.Name);
end;


 
Gym ©   (2004-03-11 15:33) [13]

to Reindeer Moss Eater

Да я уж понял что шутка. Правда сначала долго ломал голову, над тем, что ты имеешь в виду. :)))

Теперь о деле. С тем как в Data засунуть свою запись я вроде разобрался. Теперь как её оттуда вытащить.

ShowMessage("Поле MyName в записи TMyRecord имеет значение:" + PMyRecord(AThread.Data)^.MyName);

это подходит если я хочу обратиться из той же процедуры в которой
вводил данные например из procedure TfmServer.TCPServerConnect(AThread: TIdPeerThread);

А если мне нужно читать данные допустим по нажатию кнопки?
Я тут попробовал кое-что, но видно не правильно. Посмотри пожалуйста что не так.

type
 PThread = ^TIdPeerThread;
 PData = ^RDAta;
 ...

var
 CliData      : RData;
 ...

procedure TfmServer.TCPServerConnect(AThread: TIdPeerThread);
begin
 AThread.Data:=@CliData;
 PData(AThread.Data)^.Name:=("Name"+IntToStr(AllConection));
 ...
 AllConection:=AllConection+1;
end;

procedure TfmServer.Button1Click(Sender: TObject);
begin
mmLog.Lines.Add(PData(PThread(TCPServer.Threads.LockList.Items[0])^.Data)^.Name);
end;


 
Reindeer Moss Eater ©   (2004-03-11 15:44) [14]

with IdTCPServer1.Threads.LockList do
  try
   for i:= 0 to Pred(Count) do
    begin
     mmLog.Lines.Add(PMyRecord(TidPeerThread(Items[i]).Data)^.MySomeRecordField);
    end;
  finally
   IdTCPServer1.Threads.UnlockList;
  end;


 
Reindeer Moss Eater ©   (2004-03-11 15:44) [14]

with IdTCPServer1.Threads.LockList do
  try
   for i:= 0 to Pred(Count) do
    begin
     mmLog.Lines.Add(PMyRecord(TidPeerThread(Items[i]).Data)^.MySomeRecordField);
    end;
  finally
   IdTCPServer1.Threads.UnlockList;
  end;


 
Gym ©   (2004-03-11 17:26) [15]

Похоже так не получиться потому, что оператор
AThread.Data := @MyRec;
Записывает в переменную Data один и тот же адрес в памяти для
всех потоков. И если вставить этот оператор в обработчик
onConnect то каждый раз в переменную по адресу Data^ будут
записаны данные последнего потока, поверх тех что уже были.

Может чтоб реализовать хранение данных о конекте вместе с потоком
имеет смысл породить потомка от класса TIdPeerThread и добавить у него нужные поля? Или нужен потомок от класса TIdTCPServer?


 
Gym ©   (2004-03-11 17:26) [15]

Похоже так не получиться потому, что оператор
AThread.Data := @MyRec;
Записывает в переменную Data один и тот же адрес в памяти для
всех потоков. И если вставить этот оператор в обработчик
onConnect то каждый раз в переменную по адресу Data^ будут
записаны данные последнего потока, поверх тех что уже были.

Может чтоб реализовать хранение данных о конекте вместе с потоком
имеет смысл породить потомка от класса TIdPeerThread и добавить у него нужные поля? Или нужен потомок от класса TIdTCPServer?


 
Reindeer Moss Eater ©   (2004-03-11 17:31) [16]

А кто за тебя будет создавать отдельные экземпляры структур на каждого клиента Пушкин что ли?

var
MyData : PMyRecord;

New(MyData);
AThread.Data := MyData;


 
Reindeer Moss Eater ©   (2004-03-11 17:31) [16]

А кто за тебя будет создавать отдельные экземпляры структур на каждого клиента Пушкин что ли?

var
MyData : PMyRecord;

New(MyData);
AThread.Data := MyData;


 
Gym ©   (2004-03-11 18:05) [17]

to Reindeer Moss Eater

Похоже так не получиться потому, что оператор
AThread.Data := @MyRec;
Записывает в переменную Data один и тот же адрес в памяти для
всех потоков. И если вставить этот оператор в обработчик
onConnect то каждый раз в переменную по адресу Data^ будут
записаны данные последнего потока, поверх тех что уже были.

Может чтоб реализовать хранение данных о конекте вместе с потоком
имеет смысл породить потомка от класса TIdPeerThread и добавить у него нужные поля?
Или нужен потомок от класса TIdTCPServer?

а потом я провёл экспиремент. Вывел ThreadID для всех потоков вот так:

   try
     for i:= 0 to Pred(Count) do
       begin
         mmLog.Lines.Add(IntToStr(
           PThread(TCPServer.Threads.LockList.Items[i])^.ThreadID));
        end;
 finally
   TCPServer.Threads.UnlockList;
 end;

так там получилось что у всех потоков одинаковый ThreadID
и теперь я вообще ничего не пойму...
попробовал вывести тот же ThreadID так:

for i:=0 to AllConection-1 do mmLog.Lines.Add(IntToStr(Aka[i].Thread.ThreadID));

перед этим в  обработчике OnConnect написал
 Aka[i].Thread:=AThread;
тут всё нормально ThreadID разные, причём ни один не совпадает с
выведенными первым способом.

Одна надежда на тебя. Подскажи пожалуйста что тут не так?


 
Gym ©   (2004-03-11 18:05) [17]

to Reindeer Moss Eater

Похоже так не получиться потому, что оператор
AThread.Data := @MyRec;
Записывает в переменную Data один и тот же адрес в памяти для
всех потоков. И если вставить этот оператор в обработчик
onConnect то каждый раз в переменную по адресу Data^ будут
записаны данные последнего потока, поверх тех что уже были.

Может чтоб реализовать хранение данных о конекте вместе с потоком
имеет смысл породить потомка от класса TIdPeerThread и добавить у него нужные поля?
Или нужен потомок от класса TIdTCPServer?

а потом я провёл экспиремент. Вывел ThreadID для всех потоков вот так:

   try
     for i:= 0 to Pred(Count) do
       begin
         mmLog.Lines.Add(IntToStr(
           PThread(TCPServer.Threads.LockList.Items[i])^.ThreadID));
        end;
 finally
   TCPServer.Threads.UnlockList;
 end;

так там получилось что у всех потоков одинаковый ThreadID
и теперь я вообще ничего не пойму...
попробовал вывести тот же ThreadID так:

for i:=0 to AllConection-1 do mmLog.Lines.Add(IntToStr(Aka[i].Thread.ThreadID));

перед этим в  обработчике OnConnect написал
 Aka[i].Thread:=AThread;
тут всё нормально ThreadID разные, причём ни один не совпадает с
выведенными первым способом.

Одна надежда на тебя. Подскажи пожалуйста что тут не так?


 
Gym ©   (2004-03-11 20:25) [18]

to Reindeer Moss Eater

Вообщем попробовал сделать всё заново.
Привожу упрощённый текст моей программы.
Если в выделенной сторке оставить всё как есть то выскакивает ошибка:
[Error] ServUnit.pas(60): Incompatible types: "TObject" and "PMyData"
Если записать так:
 ATHread.Data:=@MyData;
То всё проходит нормально, но когда жмёшь на Button1 то получаешь ошибку. Access violation at address ... in module SERV.EXE. Write of address ... .

unit ServUnit;
interface
uses
 ...

type
 PMyData = ^RMyData;
 RMyData = record
   Name : string;
   Pass : string;
 end;

 TForm1 = class(TForm)
   Memo1: TMemo;
   Panel1: TPanel;
   IdTCPServer1: TIdTCPServer;
   IdAntiFreeze1: TIdAntiFreeze;
   Button1: TButton;
   Button2: TButton;
   Button3: TButton;
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure IdTCPServer1Connect(AThread: TIdPeerThread);
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 MyData : PMyData;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
 idTCPServer1.Active:=True;
end;

procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
var
 Name : string;
 Pass : string;
begin
 Name:=AThread.Connection.ReadLn;
 Memo1.Lines.Add(Name);
 AThread.Connection.WriteLn("GET PASS");
 Pass:=AThread.Connection.ReadLn;
 Memo1.Lines.Add(Pass);
 AThread.Connection.WriteLn("OK");
 New(MyData);
 ATHread.Data:=MyData;
 PMyData(AThread.Data)^.Name:=Name;
 PMyData(AThread.Data)^.Pass:=Pass;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 i : integer;
begin
 for i:=0 to idTCPServer1.Threads.LockList.Count-1 do
   begin
     Memo1.Lines.Add(PMyData(idTCPServer1.Threads.LockList.Items[i])^.Name);
   end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 idTCPServer1.Active:=False;
end;

end.


 
Gym ©   (2004-03-11 20:25) [18]

to Reindeer Moss Eater

Вообщем попробовал сделать всё заново.
Привожу упрощённый текст моей программы.
Если в выделенной сторке оставить всё как есть то выскакивает ошибка:
[Error] ServUnit.pas(60): Incompatible types: "TObject" and "PMyData"
Если записать так:
 ATHread.Data:=@MyData;
То всё проходит нормально, но когда жмёшь на Button1 то получаешь ошибку. Access violation at address ... in module SERV.EXE. Write of address ... .

unit ServUnit;
interface
uses
 ...

type
 PMyData = ^RMyData;
 RMyData = record
   Name : string;
   Pass : string;
 end;

 TForm1 = class(TForm)
   Memo1: TMemo;
   Panel1: TPanel;
   IdTCPServer1: TIdTCPServer;
   IdAntiFreeze1: TIdAntiFreeze;
   Button1: TButton;
   Button2: TButton;
   Button3: TButton;
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure IdTCPServer1Connect(AThread: TIdPeerThread);
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 MyData : PMyData;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
 idTCPServer1.Active:=True;
end;

procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
var
 Name : string;
 Pass : string;
begin
 Name:=AThread.Connection.ReadLn;
 Memo1.Lines.Add(Name);
 AThread.Connection.WriteLn("GET PASS");
 Pass:=AThread.Connection.ReadLn;
 Memo1.Lines.Add(Pass);
 AThread.Connection.WriteLn("OK");
 New(MyData);
 ATHread.Data:=MyData;
 PMyData(AThread.Data)^.Name:=Name;
 PMyData(AThread.Data)^.Pass:=Pass;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 i : integer;
begin
 for i:=0 to idTCPServer1.Threads.LockList.Count-1 do
   begin
     Memo1.Lines.Add(PMyData(idTCPServer1.Threads.LockList.Items[i])^.Name);
   end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 idTCPServer1.Active:=False;
end;

end.


 
Reindeer Moss Eater ©   (2004-03-11 22:04) [19]

procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
var
Name   : string;
Pass   : string;
MyData : PMyData;
begin
Name:=AThread.Connection.ReadLn;
AThread.Connection.WriteLn("GET PASS");
Pass:=AThread.Connection.ReadLn;
AThread.Connection.WriteLn("OK");
New(MyData);
ATHread.Data:=TObject(MyData);
MyData^.Name:=Name;
MyData^.Pass:=Pass;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
var i : integer;
begin
//LockList - функция. Возвращает TList. Каждый элемент в котором - экземпляр TidPeerThread
with idTCPServer1.Threads.LockList do
 try
  for i:=0 to Pred(Count) do
   Memo1.Lines.Add(PMyData(TIdPeerThread(Items[i]).Data)^.Name);
 finally
  //На каждый LockList должен быть свой UnlockList потому что каждый LockList использует критические секции
  idTCPServer1.Threads.UnlockList;
 end;
end;


 
Reindeer Moss Eater ©   (2004-03-11 22:04) [19]

procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
var
Name   : string;
Pass   : string;
MyData : PMyData;
begin
Name:=AThread.Connection.ReadLn;
AThread.Connection.WriteLn("GET PASS");
Pass:=AThread.Connection.ReadLn;
AThread.Connection.WriteLn("OK");
New(MyData);
ATHread.Data:=TObject(MyData);
MyData^.Name:=Name;
MyData^.Pass:=Pass;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
var i : integer;
begin
//LockList - функция. Возвращает TList. Каждый элемент в котором - экземпляр TidPeerThread
with idTCPServer1.Threads.LockList do
 try
  for i:=0 to Pred(Count) do
   Memo1.Lines.Add(PMyData(TIdPeerThread(Items[i]).Data)^.Name);
 finally
  //На каждый LockList должен быть свой UnlockList потому что каждый LockList использует критические секции
  idTCPServer1.Threads.UnlockList;
 end;
end;


 
Gym ©   (2004-03-12 04:43) [20]

to Reindeer Moss Eater

Огромное спасибо за потраченное на меня время.
Торжественно обещаю в ближайшее время засесть за книжки и
разобраться во всех этих обьектах, записях и полях.
А пока ещё один маленький вопрос.
Тут мы выделили память из кучи
New(MyData);
а где её лучше освободить?


 
Gym ©   (2004-03-12 04:43) [20]

to Reindeer Moss Eater

Огромное спасибо за потраченное на меня время.
Торжественно обещаю в ближайшее время засесть за книжки и
разобраться во всех этих обьектах, записях и полях.
А пока ещё один маленький вопрос.
Тут мы выделили память из кучи
New(MyData);
а где её лучше освободить?


 
Fay ©   (2004-03-12 07:35) [21]

New + F1


 
Fay ©   (2004-03-12 07:35) [21]

New + F1


 
Reindeer Moss Eater ©   (2004-03-12 08:49) [22]

а где её лучше освободить?

Когда клиент сматывает удочки


 
Reindeer Moss Eater ©   (2004-03-12 08:49) [22]

а где её лучше освободить?

Когда клиент сматывает удочки


 
Verg ©   (2004-03-12 09:32) [23]

Что-то меня сомнения берут.
Насчет new(MyData).

Data : TObject

И когда клиент "сматывает удочки", не уничтожается ли Data
Таким образом - Data.Free ???

Есть мненние, что MyData должен быть классом, а не произвольной структурой данных.


 
Verg ©   (2004-03-12 09:32) [23]

Что-то меня сомнения берут.
Насчет new(MyData).

Data : TObject

И когда клиент "сматывает удочки", не уничтожается ли Data
Таким образом - Data.Free ???

Есть мненние, что MyData должен быть классом, а не произвольной структурой данных.


 
Reindeer Moss Eater ©   (2004-03-12 09:34) [24]

Ну в общем да.

Data is not initialized in the Create constructor, but is released in the Destroy destructor.


 
Reindeer Moss Eater ©   (2004-03-12 09:34) [24]

Ну в общем да.

Data is not initialized in the Create constructor, but is released in the Destroy destructor.


 
Reindeer Moss Eater ©   (2004-03-12 09:37) [25]

Все равно никакого криминала нет.
Если в дисконнекте клиента сделать Dispose и присвоить Data:=nil;
Деструктор ничего даже не заметит.


 
Reindeer Moss Eater ©   (2004-03-12 09:37) [25]

Все равно никакого криминала нет.
Если в дисконнекте клиента сделать Dispose и присвоить Data:=nil;
Деструктор ничего даже не заметит.


 
Varg   (2004-03-12 09:39) [26]

Оригинал 9.0.14:

procedure TIdThread.Cleanup;
begin
 FreeAndNil(FData);
end;


Так что, надо бы пересмотреть

type
TMyData = class
public
  Name : string;
  Pass : string;
end;
.....................
.....................

procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
var
  Name   : string;
 Pass   : string;
 MyData : TMyData;
begin
Name:=AThread.Connection.ReadLn;
AThread.Connection.WriteLn("GET PASS");
Pass:=AThread.Connection.ReadLn;
AThread.Connection.WriteLn("OK");

MyData := TmyData.Create;
ATHread.Data:=MyData;
MyData.Name:=Name;
MyData.Pass:=Pass;

end;


 
Varg   (2004-03-12 09:39) [26]

Оригинал 9.0.14:

procedure TIdThread.Cleanup;
begin
 FreeAndNil(FData);
end;


Так что, надо бы пересмотреть

type
TMyData = class
public
  Name : string;
  Pass : string;
end;
.....................
.....................

procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
var
  Name   : string;
 Pass   : string;
 MyData : TMyData;
begin
Name:=AThread.Connection.ReadLn;
AThread.Connection.WriteLn("GET PASS");
Pass:=AThread.Connection.ReadLn;
AThread.Connection.WriteLn("OK");

MyData := TmyData.Create;
ATHread.Data:=MyData;
MyData.Name:=Name;
MyData.Pass:=Pass;

end;


 
Reindeer Moss Eater ©   (2004-03-12 09:41) [27]

Ничего не надо пересматривать.
Если Data не доживет до деструктора, то ровным счетом ничего криминального не случится. Чем бы эта дата ни была.


 
Reindeer Moss Eater ©   (2004-03-12 09:41) [27]

Ничего не надо пересматривать.
Если Data не доживет до деструктора, то ровным счетом ничего криминального не случится. Чем бы эта дата ни была.


 
Gym ©   (2004-03-12 14:50) [28]

Честно говоря пока всё равно ничего не получается. Выскакивают
Acces violation error всякие. Ну да уж с этим я сам попробую
разобраться. Благо информации для размышления вы мне подкинули
достаточно.
 Отдельное спасибо Reindeer Moss Eater хорошо что есть люди которым не лень возиться с такими как я. :)))


 
Gym ©   (2004-03-12 14:50) [28]

Честно говоря пока всё равно ничего не получается. Выскакивают
Acces violation error всякие. Ну да уж с этим я сам попробую
разобраться. Благо информации для размышления вы мне подкинули
достаточно.
 Отдельное спасибо Reindeer Moss Eater хорошо что есть люди которым не лень возиться с такими как я. :)))


 
Gym ©   (2004-03-13 06:16) [29]

И так если  кому интересно, привожу полный текст моей работающей программы ( если эту программу можно назвать моей :) ). Ещё раз спасибо всем тем, кто помогал мне.

unit ServUnit;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, IdAntiFreezeBase, IdAntiFreeze, IdBaseComponent, IdComponent,
 IdTCPServer, Buttons, StdCtrls, ExtCtrls;

type
PMyData = ^RMyData;
RMyData = record
  Name : string;
  Pass : string;
end;

 TForm1 = class(TForm)
   Panel1: TPanel;
   Memo1: TMemo;
   SpeedButton1: TSpeedButton;
   IdTCPServer1: TIdTCPServer;
   IdAntiFreeze1: TIdAntiFreeze;
   procedure IdTCPServer1Execute(AThread: TIdPeerThread);
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure SpeedButton1Click(Sender: TObject);
   procedure IdTCPServer1Connect(AThread: TIdPeerThread);
   procedure IdTCPServer1Disconnect(AThread: TIdPeerThread);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1    : TForm1;
 SecondID : cardinal;
 count    : integer;
 MyData   : PMyData;
implementation

{$R *.dfm}

procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
begin
 Memo1.Lines.Add(AThread.Connection.ReadLn);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 IdTCPServer1.Active:=True;
 SecondID:=0;
 count:=0;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 IdTCPServer1.Active:=False;
end;

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
 i : integer;
begin
 try
 for i:=0 to IdTCPServer1.Threads.LockList.Count-1 do
   begin
     Memo1.Lines.Add(IntToStr(TIdPeerThread(IdTCPServer1.Threads.LockList.Items[i]).ThreadID));
     IdTCPServer1.Threads.UnlockList;
     Memo1.Lines.Add(PMyData(TIdPeerThread(IdTCPServer1.Threads.LockList.Items[i]).Data).Name);
     IdTCPServer1.Threads.UnlockList;
   end;
 finally

 IdTCPServer1.Threads.UnlockList;
   end;
end;

procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
var
 Name : string;
 Pass : string;
begin
 AThread.Connection.WriteLn("GN");
 Name:=AThread.Connection.ReadLn;
 Memo1.Lines.Add(Name);
 AThread.Connection.WriteLn("GP");
 Pass:=AThread.Connection.ReadLn;
 Memo1.Lines.Add(Pass);
 AThread.Connection.WriteLn("OK");
 New(MyData);
 ATHread.Data:=TObject(MyData);
 MyData^.Name:=Name;
 MyData^.Pass:=Pass;
end;

procedure TForm1.IdTCPServer1Disconnect(AThread: TIdPeerThread);
begin
 Memo1.Lines.Add("Disconnect: "+IntToStr(AThread.ThreadID)+PMyData(AThread.Data).Name);
 AThread.Data:=nil;
end;
end.


 
Gym ©   (2004-03-13 06:16) [29]

И так если  кому интересно, привожу полный текст моей работающей программы ( если эту программу можно назвать моей :) ). Ещё раз спасибо всем тем, кто помогал мне.

unit ServUnit;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, IdAntiFreezeBase, IdAntiFreeze, IdBaseComponent, IdComponent,
 IdTCPServer, Buttons, StdCtrls, ExtCtrls;

type
PMyData = ^RMyData;
RMyData = record
  Name : string;
  Pass : string;
end;

 TForm1 = class(TForm)
   Panel1: TPanel;
   Memo1: TMemo;
   SpeedButton1: TSpeedButton;
   IdTCPServer1: TIdTCPServer;
   IdAntiFreeze1: TIdAntiFreeze;
   procedure IdTCPServer1Execute(AThread: TIdPeerThread);
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure SpeedButton1Click(Sender: TObject);
   procedure IdTCPServer1Connect(AThread: TIdPeerThread);
   procedure IdTCPServer1Disconnect(AThread: TIdPeerThread);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1    : TForm1;
 SecondID : cardinal;
 count    : integer;
 MyData   : PMyData;
implementation

{$R *.dfm}

procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
begin
 Memo1.Lines.Add(AThread.Connection.ReadLn);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 IdTCPServer1.Active:=True;
 SecondID:=0;
 count:=0;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 IdTCPServer1.Active:=False;
end;

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
 i : integer;
begin
 try
 for i:=0 to IdTCPServer1.Threads.LockList.Count-1 do
   begin
     Memo1.Lines.Add(IntToStr(TIdPeerThread(IdTCPServer1.Threads.LockList.Items[i]).ThreadID));
     IdTCPServer1.Threads.UnlockList;
     Memo1.Lines.Add(PMyData(TIdPeerThread(IdTCPServer1.Threads.LockList.Items[i]).Data).Name);
     IdTCPServer1.Threads.UnlockList;
   end;
 finally

 IdTCPServer1.Threads.UnlockList;
   end;
end;

procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
var
 Name : string;
 Pass : string;
begin
 AThread.Connection.WriteLn("GN");
 Name:=AThread.Connection.ReadLn;
 Memo1.Lines.Add(Name);
 AThread.Connection.WriteLn("GP");
 Pass:=AThread.Connection.ReadLn;
 Memo1.Lines.Add(Pass);
 AThread.Connection.WriteLn("OK");
 New(MyData);
 ATHread.Data:=TObject(MyData);
 MyData^.Name:=Name;
 MyData^.Pass:=Pass;
end;

procedure TForm1.IdTCPServer1Disconnect(AThread: TIdPeerThread);
begin
 Memo1.Lines.Add("Disconnect: "+IntToStr(AThread.ThreadID)+PMyData(AThread.Data).Name);
 AThread.Data:=nil;
end;
end.


 
Verg ©   (2004-03-13 08:07) [30]


> procedure TForm1.IdTCPServer1Disconnect(AThread: TIdPeerThread);
> begin
>  Memo1.Lines.Add("Disconnect: "+IntToStr(AThread.ThreadID)+PMyData(AThread.Data).Name);
  dispose(PMyData(AThread.Data));
>  AThread.Data:=nil;
> end;


 
Verg ©   (2004-03-13 08:07) [30]


> procedure TForm1.IdTCPServer1Disconnect(AThread: TIdPeerThread);
> begin
>  Memo1.Lines.Add("Disconnect: "+IntToStr(AThread.ThreadID)+PMyData(AThread.Data).Name);
  dispose(PMyData(AThread.Data));
>  AThread.Data:=nil;
> end;


 
Gym ©   (2004-03-13 15:53) [31]

to Varg
 
После того как заменил свой оператор
AThread.Data:=nil;
на твой
dispose(PMyData(AThread.Data));
при дисконекте в режиме запуска проги из под делфи
выскакивает окошко:

Project ... raised exception class EAccessViolation with
message "Access violation at address ... Write of adress ...
Process stoped.


Если же прогу запускать саму по себе, из операционки то после
первого же дисконекта (который внешне проходит вроде бы нормально), она спотыкается на обработчике нажатия Button1.
Выкидывает окошко следующего содержания:

"Access violation at address ... Read of adress ...

Мой оператор (который с nil) он уничтожает обьект но не возвращает память в кучу, да? Т.е. при достаточном кол-ве конектов/дисконектов прога может забрать всю доступную динамическую память?


 
Gym ©   (2004-03-13 15:53) [31]

to Varg
 
После того как заменил свой оператор
AThread.Data:=nil;
на твой
dispose(PMyData(AThread.Data));
при дисконекте в режиме запуска проги из под делфи
выскакивает окошко:

Project ... raised exception class EAccessViolation with
message "Access violation at address ... Write of adress ...
Process stoped.


Если же прогу запускать саму по себе, из операционки то после
первого же дисконекта (который внешне проходит вроде бы нормально), она спотыкается на обработчике нажатия Button1.
Выкидывает окошко следующего содержания:

"Access violation at address ... Read of adress ...

Мой оператор (который с nil) он уничтожает обьект но не возвращает память в кучу, да? Т.е. при достаточном кол-ве конектов/дисконектов прога может забрать всю доступную динамическую память?


 
Verg ©   (2004-03-13 15:56) [32]


> [31] Gym ©   (13.03.04 15:53)
> to Varg
>  
> После того как заменил свой оператор
> AThread.Data:=nil;
> на твой
> dispose(PMyData(AThread.Data));


Кто ж тебе сказал заменять?

Я же написал - добавить перед, а не заменить.
Что с глазами?


 
Verg ©   (2004-03-13 15:56) [32]


> [31] Gym ©   (13.03.04 15:53)
> to Varg
>  
> После того как заменил свой оператор
> AThread.Data:=nil;
> на твой
> dispose(PMyData(AThread.Data));


Кто ж тебе сказал заменять?

Я же написал - добавить перед, а не заменить.
Что с глазами?


 
Verg ©   (2004-03-13 15:58) [33]

Утечка памяти - знаешь что такое?


 
Verg ©   (2004-03-13 15:58) [33]

Утечка памяти - знаешь что такое?


 
Verg ©   (2004-03-13 16:05) [34]


> Мой оператор (который с nil) он уничтожает обьект но не
> возвращает память в кучу, да? Т.е. при достаточном кол-ве
> конектов/дисконектов прога может забрать всю доступную динамическую
> память?


Похоже догадываешься.

Data := nil - не уничтожает. Он присваевает значение nil и все больше ничего. Хотя в данном случае это тоже нужно и важно. Т.к. при уничтожении потока, в деструкторе произойдет уничтожение объекта Data (см. несколко выше - я писал). Т.е. Data.Free. Если объект  Data = nil, то Free просто ничего не сделает: особенный такой случай. Но память-то надо освободить (вернуть в кучу). Так что, dispose просто необходим.


 
Verg ©   (2004-03-13 16:05) [34]


> Мой оператор (который с nil) он уничтожает обьект но не
> возвращает память в кучу, да? Т.е. при достаточном кол-ве
> конектов/дисконектов прога может забрать всю доступную динамическую
> память?


Похоже догадываешься.

Data := nil - не уничтожает. Он присваевает значение nil и все больше ничего. Хотя в данном случае это тоже нужно и важно. Т.к. при уничтожении потока, в деструкторе произойдет уничтожение объекта Data (см. несколко выше - я писал). Т.е. Data.Free. Если объект  Data = nil, то Free просто ничего не сделает: особенный такой случай. Но память-то надо освободить (вернуть в кучу). Так что, dispose просто необходим.


 
Gym ©   (2004-03-13 17:20) [35]

to Verg

> Я же написал - добавить перед, а не заменить.
> Что с глазами?

Сорри, с недосыпу ещё и не то примерещиться.
Теперь всё работает как часы. Спасибо.


 
Gym ©   (2004-03-13 17:20) [35]

to Verg

> Я же написал - добавить перед, а не заменить.
> Что с глазами?

Сорри, с недосыпу ещё и не то примерещиться.
Теперь всё работает как часы. Спасибо.


 
Gym ©   (2004-03-13 17:35) [36]

to Verg


> Data := nil - не уничтожает. Он присваевает значение nil
> и все больше ничего.


"Библия Делфи" автор Horrific www.vr-online.ru

 А что если у тебя две переменные указывают на один и тот же адрес данных? Неужели при уничтожении одного из них данные уничтожаться и вторая переменная будет указывать на несуществующие данные? Нет, обьект будет уничтожен только после того, как все указатели на него будут уничтожены.

Видимо не правильно понял.


 
Gym ©   (2004-03-13 17:35) [36]

to Verg


> Data := nil - не уничтожает. Он присваевает значение nil
> и все больше ничего.


"Библия Делфи" автор Horrific www.vr-online.ru

 А что если у тебя две переменные указывают на один и тот же адрес данных? Неужели при уничтожении одного из них данные уничтожаться и вторая переменная будет указывать на несуществующие данные? Нет, обьект будет уничтожен только после того, как все указатели на него будут уничтожены.

Видимо не правильно понял.


 
nikkie ©   (2004-03-13 18:17) [37]

судя по приведенной цитате, можно рекомендовать эту книгу не читать.


 
nikkie ©   (2004-03-13 18:17) [37]

судя по приведенной цитате, можно рекомендовать эту книгу не читать.


 
Verg ©   (2004-03-13 18:24) [38]


>  А что если у тебя две переменные указывают на один и тот
> же адрес данных? Неужели при уничтожении одного из них данные
> уничтожаться и вторая переменная будет указывать на несуществующие
> данные? Нет, обьект будет уничтожен только после того, как
> все указатели на него будут уничтожены.


Я этого тоже не понимаю. Это по какой теме?
Может это "фокусы" ("жертва") некачественного перевода на русский?

Объект (блок памяти, record, class) будет уничтожен, а точее память им занимаемая будет отнесена к пулу свободной (доступной для последующего распределения), так сразу, как только будет вызвана процедура делающее это(.free, freemem, dispose, localfree, и т.п.).

Может там речь шла об объектах ядра или тому подобных механизмах? И ф-циях типа CloseHandle - так это тогда совсем другая "опера".


 
Verg ©   (2004-03-13 18:24) [38]


>  А что если у тебя две переменные указывают на один и тот
> же адрес данных? Неужели при уничтожении одного из них данные
> уничтожаться и вторая переменная будет указывать на несуществующие
> данные? Нет, обьект будет уничтожен только после того, как
> все указатели на него будут уничтожены.


Я этого тоже не понимаю. Это по какой теме?
Может это "фокусы" ("жертва") некачественного перевода на русский?

Объект (блок памяти, record, class) будет уничтожен, а точее память им занимаемая будет отнесена к пулу свободной (доступной для последующего распределения), так сразу, как только будет вызвана процедура делающее это(.free, freemem, dispose, localfree, и т.п.).

Может там речь шла об объектах ядра или тому подобных механизмах? И ф-циях типа CloseHandle - так это тогда совсем другая "опера".


 
nikkie ©   (2004-03-13 18:45) [39]

>Может это "фокусы" ("жертва") некачественного перевода на русский?
не, это русский пишет.

>Это по какой теме?
тема называется "Указатели", перед этим есть какой-то разговор о строках, но в данном случае уже не про них речь.

предыдущее предложение:
Точно так же, если ты переменной объекту присвоишь нулевое значение, ты его уничтожишь, и объект больше не будет существовать.

http://www.podgoretsky.com/ftp/Docs/Delphi/Fleonov/Bibble/Ch%2010.pdf


 
nikkie ©   (2004-03-13 18:45) [39]

>Может это "фокусы" ("жертва") некачественного перевода на русский?
не, это русский пишет.

>Это по какой теме?
тема называется "Указатели", перед этим есть какой-то разговор о строках, но в данном случае уже не про них речь.

предыдущее предложение:
Точно так же, если ты переменной объекту присвоишь нулевое значение, ты его уничтожишь, и объект больше не будет существовать.

http://www.podgoretsky.com/ftp/Docs/Delphi/Fleonov/Bibble/Ch%2010.pdf


 
Verg ©   (2004-03-13 19:04) [40]


> Точно так же, если ты переменной объекту присвоишь нулевое
> значение, ты его уничтожишь, и объект больше не будет существовать.


Я ху... фигею в этом зоопарке..... :((


 
Verg ©   (2004-03-13 19:04) [40]


> Точно так же, если ты переменной объекту присвоишь нулевое
> значение, ты его уничтожишь, и объект больше не будет существовать.


Я ху... фигею в этом зоопарке..... :((



Страницы: 1 2 вся ветка

Форум: "Сети";
Текущий архив: 2004.04.11;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.72 MB
Время: 0.131 c
1-1082551540
vin
2004-04-21 16:45
2004.05.09
PopupMenu на раскрытом ComboBox-е


14-1081911090
Ильш
2004-04-14 06:51
2004.05.09
ВСЕМ ! ВСЕМ ! ВСЕМ !


14-1082366952
Vlad Oshin
2004-04-19 13:29
2004.05.09
пошловато, но, уверен, улыбнетесь :)


8-1076386138
scorpi
2004-02-10 07:08
2004.05.09
OpenGL


4-1079956507
Yourik
2004-03-22 14:55
2004.05.09
Криптография, CryptGenKey(), CryptEncrypt()... etc





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский