Форум: "Сети";
Текущий архив: 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.035 c