Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

TIdCmdTCPServer


Страницы:   1 2 3 4 5 6 7 8

Zalm ©   (2009-08-31 13:14:00) 

Здравствуйте, как у TIdCmdTCPServer можно всем клиентам разослать сообщение? Надо например каждому отослать команду. Это должно быть естественно в цикле, только я не знаю как и где. У TServerSocket было проще всё, ну или понятней.
1)Вот например у меня есть кнопка на сервере, как сделать чтоб ы при нажатии на кнопку каждому подключению что-то отправить, и что бы узнать его адрес там и тд?
2) Как узнать ip и handler подключения? и в каком евенте... если в OnConnect то я не опнля как...
3) Как вне событий отправить текст на подключение с известным адресом\обработчкиом?
Буду очень благодарен за помощь.


Zalm   (2009-09-19 22:23:00) [21]


> неправильно. причем неправильно не из за секций.

а почему не сказал из-за чего :(

Сергей, вы так и не сказали секции правильно или нет...

Про try..finally слышал, я его обычно для ошибок использую Try..Except


Anatoly Podgoretsky   (2009-09-19 20:48:00) [22]

> Сергей М.  (19.09.2009 15:23:08)  [128]

select from insert to
 "Сергей М."
сообщил/сообщила в
новостях следующее:
news:1251710046.128@delphimaster.ru...
 Сергей М. © (19.09.2009 15:23) [128]

 > edit1.Text


 Это тоже
потоконебезопасное
обращение.

 Ты, кстати, про try..finally
что-нибудь слышал ?


Сергей М.   (2009-09-19 15:23:00) [23]


> edit1.Text


Это тоже потоконебезопасное обращение.

Ты, кстати, про try..finallyчто-нибудь слышал ?


Медвежонок Пятачок   (2009-09-19 01:30:00) [24]

неправильно. причем неправильно не из за секций.


Zalm   (2009-09-19 01:25:00) [25]


> Чего ж ты тогда продолжаешь топик и постишь код, при котором
> "всем стало хорошо" ?)

))))

Так с крит секциями правильно?


procedure TForm1.ServerConnect(AContext: TIdContext);
var
str, IP : string;
I : integer;
Port:Word;
KEY_CHECK : String;
begin
KEY_CHECK:=Acontext.Connection.Socket.Readln();
if edit1.Text<>KEY_CHECK then Acontext.Connection.Disconnect;
AContext.Connection.Socket.Writeln('Index[<=10]');
str:=Acontext.Connection.Socket.ReadLn();
if length(str)>10 then Acontext.Connection.Disconnect;
CriticalSection.Enter;
for I := 0 to Clients.Count - 1 do
 begin
  if Clients.Clients[i].Index=str then
   begin
    if Clients.Clients[i].SIP='' then
     begin
      Clients.Clients[i].SIP:=Acontext.Connection.Socket.Binding.PeerIP;
      Clients.Clients[i].SPort:=AContext.Connection.Socket.Binding.PeerPort;
      Acontext.Connection.Socket.WriteLn('srd');
      CriticalSection.Leave;
      exit;
     end;
    if Clients.Clients[i].PIP='' then
     begin
      Clients.Clients[i].PIP:=Acontext.Connection.Socket.Binding.PeerIP;
      Clients.Clients[i].PPort:=AContext.Connection.Socket.Binding.PeerPort;
      Acontext.Connection.Socket.WriteLn('srd');
      CriticalSection.Leave;
      exit;
     end;
    AContext.Connection.Disconnect;
    CriticalSection.Leave;
    exit;
   end;
 end;
inc(Clients.Count);
SetLength(Clients.Clients,Clients.Count);
Clients.Clients[Clients.Count-1].SIP:=AContext.Connection.Socket.Binding.PeerIP;
Clients.Clients[Clients.Count-1].SPort:=AContext.Connection.Socket.Binding.PeerPort;
Clients.Clients[Clients.Count-1].Index:=str;
CriticalSection.Leave;
Acontext.Connection.Socket.WriteLn('srd');
end;


Сергей М.   (2009-09-18 17:21:00) [26]


> так дело никуда не сдвинется


Конечно не сдвинется..
Думать-то ты по-прежнему не хочешь..


> с ним вылазили ошибки, а без него всем стало хорошо


Чего ж ты тогда продолжаешь топик и постишь код, при котором "всем стало хорошо" ?)


Zalm   (2009-09-18 17:16:00) [27]


> Я ж палец сломаю, если буду в каждую тыкать : весь этот
> код - одна сплошная большая ошибка)

ну так дело никуда не сдвинется... не хорошо так..


> Вот скажи, ты за каким создал объект CriticalSection, если
> нигде кроме как в Form1.OnCreate его в последствии не используешь
> для защиты ресурса Clients ?

Раньше использховал, в ONConnect и OnDisconnect, но с ним вылазили ошибки, а без него всем стало хорошо xD
Я попробую это исправить.


Сергей М.   (2009-09-18 17:06:00) [28]

Я ж палец сломаю, если буду в каждую тыкать : весь этот код - одна сплошная большая ошибка)

Вот скажи, ты за каким создал объект CriticalSection, если нигде кроме как в Form1.OnCreate его в последствии не используешь для защиты ресурса Clients ?
И от кого ты защищаешь ресурс Clients при обработке события Form1.OnCreate, если в этот момент не существует ни единого потока кроме основного ?


Zalm   (2009-09-18 16:53:00) [29]


Procedure Server_clear;
var
list : TList;
i : integer;
begin
try
 LIst:=Form1.Server.Contexts.LockList;
 for I := 0 to List.Count - 1 do
  with TidContext(List[i]) do Connection.Disconnect;
finally
 Form1.Server.Contexts.UnlockList;
end;
Clients.Count:=0;
SetLength(Clients.Clients,0);
end;

procedure TForm1.ServerExecute(AContext: TIdContext);
var
MSG : string;
I, J : integer;
List : Tlist;
_ip : string;
_port : word;
key : string;
begin
msg:=AContext.Connection.Socket.ReadLn();
{----------------------------------------}
if msg='\reset\' then
 begin
  Server_clear;
 end;
if msg='\сhKOL\' then
 begin

 end;
if msg='\chKEY\' then
 begin
  AContext.Connection.Socket.Writeln('KEY');
  key:=AContext.Connection.Socket.Readln();
  if KEY<>Edit2.Text then
   begin
    AContext.Connection.Socket.WriteLn('ikr');   {invalid key read}
    Acontext.Connection.Disconnect;
    exit;
   end
  else
   begin
    AContext.Connection.Socket.WriteLn('NK');    {new key}
    KEY:=AContext.Connection.Socket.ReadLn();
    if Length(key)>10 then
     begin
      AContext.Connection.Socket.WriteLn('iks'); {invalid key set}
      AContext.Connection.Disconnect;
      exit;
     end
    else
     begin
      Acontext.Connection.Socket.Write('oks');    {ok key set}
      Edit1.Text:=key;
      exit;
     end;
   end;
 end;
if msg='\clients\' then
 begin
  Acontext.Connection.Socket.WriteLn(IntToStr(Clients.Count));
  exit;
 end;
if msg='\exit\' then
 begin
  AContext.Connection.Disconnect;
  exit;
 end;
if msg='\data\' then
 begin
  for i := 0 to Clients.Count - 1 do
   begin
    Acontext.Connection.Socket.WriteLn('SIP: '+Clients.Clients[i].SIP);
    AContext.Connection.Socket.WriteLn('SPort: '+IntToStr(Clients.Clients[i].SPort));
    AContext.Connection.Socket.WriteLn('PIP: '+Clients.Clients[i].PIP);
    AContext.Connection.Socket.WriteLn('PPort: '+IntToStr(Clients.Clients[i].PPort));
    AContext.Connection.Socket.WriteLn('Index: '+Clients.Clients[i].Index);
   end;
  exit;
 end;
if msg='\i\' then
 begin
  AContext.Connection.Socket.WriteLn(AContext.Connection.Socket.Binding.PeerIP+':'+IntToStr(AContext.Connection.Socket.Binding.PeerPort));
  exit;
 end;
{----------------------------------------}
for i := 0 to Clients.Count - 1 do
 begin
  if ((Clients.Clients[i].SIP=AContext.Connection.Socket.Binding.PeerIP)and(Clients.C lients[i].SPort=AContext.Connection.Socket.Binding.PeerPort))or
     ((Clients.Clients[i].PIP=Acontext.Connection.Socket.Binding.PeerIP)and(Clients.C lients[i].PPort=AContext.Connection.Socket.Binding.PeerPort)) then
   begin
    if (Clients.Clients[i].SIP=AContext.Connection.Socket.Binding.PeerIP)and
       (Clients.Clients[i].SPort=AContext.Connection.Socket.Binding.PeerPort) then
     begin
      _ip:=Clients.Clients[i].PIP;
      if _ip='' then
       begin
        AContext.Connection.Socket.WriteLn('No send.');
        exit;
       end;
      _port:=Clients.Clients[i].PPort;
      Send(_ip,_port,msg);
      exit;
     end
    else
     begin
      _ip:=Clients.Clients[i].SIP;
      if _ip='' then
       begin
        AContext.Connection.Socket.WriteLn('No send.');
        exit;
       end;
      _port:=Clients.Clients[i].SPort;
      Send(_ip,_port,msg);
      exit;
     end;
   end
  else
   begin

   end;
 end;
end;

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
form2.show;
end;

procedure TForm1.SpeedButton2Click(Sender: TObject);
begin
Application.Terminate;
end;

procedure TForm1.SpeedButton3Click(Sender: TObject);
begin
Tray.Visible:=True;
Form1.Hide;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
day : integer;
pmc:PPROCESS_MEMORY_COUNTERS;
begin
cl.Caption:=IntToStr(Clients.Count*2);
Start_time.Caption:=TimeToStr(_Start_time);

if Abs(_Start_time-now)>1 then
  begin
   day:=Abs(Trunc(_Start_time-now));
   form1.work_time.Caption:=FloatToStr(day)+' д. '+TimeToStr(_Start_time-now);
  end
 else form1.work_time.Caption:=TimeToStr(now-_Start_time);

GetMem(pmc, SizeOf(_PROCESS_MEMORY_COUNTERS));
pmc.cb:=SizeOf(_PROCESS_MEMORY_COUNTERS);
If GetProcessMemoryInfo(GetCurrentProcess(), pmc, pmc.cb) then
 begin
  ram.Caption:=FloatToStrF((pmc^.WorkingSetSize)/1024/1024,ffFixed,15,3)+' Мб';
  FreeMem(pmc);
 end;
end;

procedure TForm1.TrayClick(Sender: TObject);
begin
Form1.Show;
Tray.Visible:=False;
end;

Procedure Send (ip:string;port:word;str:string);
var
i : integer;
List : Tlist;
begin
try
 LIst:=Form1.Server.Contexts.LockList;
 for I := 0 to List.Count - 1 do
  with TidContext(List[i]) do
   begin
    if (connection.Socket.Binding.PeerIP=ip)and(connection.Socket.Binding.PeerPort=port ) then
     begin
      TidCOntext(list[i]).Connection.Socket.WriteLn(str);
      break;
     end;
   end;
finally
 Form1.Server.Contexts.UnlockList;
end;
end;


Zalm   (2009-09-18 16:52:00) [30]


> нельзя использовать тип string generic, а не fundamental

а побольше про это слов скажете?)

Сергей, прошу тыкать пальцем, где ошибки



    _Pack = record
         SIP : string[15];
         SPort : WORD;
         PIP : string[15];
         PPort : Word;
         Index : String[10];
        end;

 _Clients = class
             pack : _pack;
             Clients : Array of _pack;
             Count : integer;
            end;

 Procedure Send (ip:string;port:word;str:string);
 Procedure Server_clear;

var

 Link_file : TEXTFILE;
 RAM_file : TEXTFILE;

 Form1: TForm1;
 Clients : _Clients;
 _null : _pack;
 CriticalSection : TCriticalSection;

 _Start_time : TDATETIME;

 Last_ram : real;

implementation

{$R *.dfm}

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Server.StopListening;
APPLICATION.Terminate;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
AssignFIle(Link_file,'link.sf');
AssignFIle(RAM_file,'ram.sf');
Rewrite(link_file);
Rewrite(ram_file);
CloseFile(link_file);
CloseFile(Ram_file);

_Start_time:=now;
CriticalSection:=TCriticalSection.Create;
CriticalSection.Enter;
Clients:=_Clients.Create;
CriticalSection.Leave;
Server.MaxConnections:=Limits.Value;
cl_limit.Caption:=IntTOstr(limits.Value);
end;

procedure TForm1.limitsClick(Sender: TObject);
begin
Server.MaxConnections:=Limits.Value;
cl_limit.Caption:=IntToStr(limits.Value);
end;

procedure TForm1.logTimer(Sender: TObject);
Var
pmc:PPROCESS_MEMORY_COUNTERS;
rm : real;
state : string;
begin
state:='';
Append(ram_file);
GetMem(pmc, SizeOf(_PROCESS_MEMORY_COUNTERS));
pmc.cb:=SizeOf(_PROCESS_MEMORY_COUNTERS);
If GetProcessMemoryInfo(GetCurrentProcess(), pmc, pmc.cb) then rm:=(pmc^.WorkingSetSize)/1024/1024;
if (rm>last_ram) then
 begin
  state:='+'+FloatToStrF(rm-Last_ram,ffFixed,15,3);
 end;
if (rm<last_ram) then
 begin
  state:='-'+FloatToStrF(last_ram-rm,ffFixed,15,3);
 end;
if rm=last_ram then State:='0';
Last_ram:=rm;
Writeln(ram_file,DateToStr(now)+' '+TimeToStr(now)+' \ RAM: '+FloatTOStrF(rm,ffFixed,15,3)+'\ '+state);
CloseFile(ram_file);
end;

procedure TForm1.displayClick(Sender: TObject);
var
str : string;
begin
RichEdit1.Clear;
if display.ItemIndex=0 then
 begin
   RichEdit1.Lines.Add('not supported');
 end;
if display.ItemIndex=1 then
 begin
  reset(ram_file);
  while not(eof(ram_file)) do
   begin
    readln(ram_file,str);
    RichEdit1.Lines.Add(str);
   end;
  RichEdit1.Lines.Add('---------------------'+#13+' END');
  closeFIle(ram_file);
 end;
end;

procedure TForm1.ServerConnect(AContext: TIdContext);
var
str, IP : string;
I : integer;
Port:Word;
KEY_CHECK : String;
begin
KEY_CHECK:=Acontext.Connection.Socket.Readln();
if edit1.Text<>KEY_CHECK then Acontext.Connection.Disconnect;
AContext.Connection.Socket.Writeln('Index[<=10]');
str:=Acontext.Connection.Socket.ReadLn();
if length(str)>10 then Acontext.Connection.Disconnect;
for I := 0 to Clients.Count - 1 do
 begin
  if Clients.Clients[i].Index=str then
   begin
    if Clients.Clients[i].SIP='' then
     begin
      Clients.Clients[i].SIP:=Acontext.Connection.Socket.Binding.PeerIP;
      Clients.Clients[i].SPort:=AContext.Connection.Socket.Binding.PeerPort;
      Acontext.Connection.Socket.WriteLn('srd');
      exit;
     end;
    if Clients.Clients[i].PIP='' then
     begin
      Clients.Clients[i].PIP:=Acontext.Connection.Socket.Binding.PeerIP;
      Clients.Clients[i].PPort:=AContext.Connection.Socket.Binding.PeerPort;
      Acontext.Connection.Socket.WriteLn('srd');
      exit;
     end;
    AContext.Connection.Disconnect;
    exit;
   end;
 end;
inc(Clients.Count);
SetLength(Clients.Clients,Clients.Count);
Clients.Clients[Clients.Count-1].SIP:=AContext.Connection.Socket.Binding.PeerIP;
Clients.Clients[Clients.Count-1].SPort:=AContext.Connection.Socket.Binding.PeerPort;
Clients.Clients[Clients.Count-1].Index:=str;
Acontext.Connection.Socket.WriteLn('srd');
end;

procedure TForm1.ServerDisconnect(AContext: TIdContext);
var
i, j : integer;
begin
for i := 0 to Clients.Count - 1 do
 begin
  if (Clients.Clients[i].SIP+':'+IntToStr(Clients.Clients[i].SPort)=AContext.Connection.Socket.Binding.PeerIP+':'+IntToStr(AContext.Connection.Socket.Binding.PeerPort)) then
   begin
    Clients.Clients[i].SIP:='';
    Clients.Clients[i].SPort:=0;
    break;
   end;
  if (Clients.Clients[i].PIP+':'+IntToStr(Clients.Clients[i].PPort)=AContext.Connection.Socket.Binding.PeerIP+':'+IntToStr(AContext.Connection.Socket.Binding.PeerPort)) then
   begin
    Clients.Clients[i].PIP:='';
    Clients.Clients[i].PPort:=0;
    break;
   end;
 end;
if (clients.Clients[i].SIP='')and(clients.Clients[i].PIP='') then
 begin
  for j := i to clients.Count - 1 do
   Clients.Clients[j]:=Clients.Clients[j+1];
  dec(clients.Count);
  SetLength(clients.Clients,Clients.Count);
 end;
end;


Anatoly Podgoretsky   (2009-09-18 13:34:00) [31]


> MSG : string;
> I, J : integer;
> List : Tlist;
> _ip : string;
> _port : word;
> key : string;

Слова плохие будут, вот здесь плохие имена, почти все, ну ладно это дело компилятора, а вот типы уже не дело компилятора - нельзя использовать тип string generic, а не fundamental - особенно для сетевых протоколов. В Инди с этим уже много дел натворили.


Сергей М.   (2009-09-18 08:18:00) [32]


> Такое у меня уже есть


Выкинь в топку.
Абсолютно бестолковый код.


> в других местах почему-то лаги


У тебя ошибки в программе.


Zalm   (2009-09-17 20:33:00) [33]


> Но тогда и гонор знайки совсем неуместен)

вот этого не понял


> Алгоритм простой:
> 1. Войти в крит.секцию.2. Обратиться к
> ресурсу.3. Выйти из крит.секции.


Всё было бы шикарно если бы не было бы затыков. Такое у меня уже есть.


procedure TForm1.FormCreate(Sender: TObject);
begin
_Start_time:=now;
CriticalSection:=TCriticalSection.Create;
CriticalSection.Enter;
Clients:=_Clients.Create;
CriticalSection.Leave;
Server.MaxConnections:=Limits.Value;
cl_limit.Caption:=IntTOstr(limits.Value);
end;


Да вот только в других местах почему-то лаги, если обращаться через крит секцию то иногда выдает ошибки памяти или вобще потом программа не выключается нормально, только в процессах убивать если


Сергей М.   (2009-09-17 19:59:00) [34]

И все-таки ты занимаешься откровенной херней.
Если это учебнаязадача, то она еще как-то оправдана в реализации.
Но тогда и гонор знайки совсем неуместен)
Если же не учебная, то достаточно попросить админа пробросить порт на твой хост. На своем хосте ты волен развернуть хоть VPN, хоть черта лысого)


Сергей М.   (2009-09-17 19:48:00) [35]

Алгоритм простой:

1. Войти в крит.секцию.
2. Обратиться к ресурсу.
3. Выйти из крит.секции.


Zalm   (2009-09-17 19:42:00) [36]

нет, ну просто алгоритм скажите пожалуйста как делать


Сергей М.   (2009-09-17 19:32:00) [37]

В смысле ?
Программу что ли за тебя написать ?


Zalm   (2009-09-17 17:44:00) [38]


> > Процедуры подключения и отключения клиентов используют
> один > и тот же массив, что будет когда неск клиентов столкнутся
> > на одном и том же массиве, в том смысле то есть что он
> им > обоим будет нужен сразу?Грабли будут.Доступ к потоконебезопасному
> ресурсу обязателен к синхронизации.> что будет если кто-
> то из клиентов соберется что-то отправить,>  в то время
> как УЖЕ будет работать процедура Send вызванная > предыдущим
> клиентом?Этот "кто-то" застрянет на LockList до тех пор,
>  пока предыдущий "кто-то" не вызовет UnlockList.


и как мне всё это исправить что бы было как надо?


Сергей М.   (2009-09-17 17:23:00) [39]


> Сервер не предназначем для чата


Фиолетово для чего он предназначен.
Преведбыл выбран как абстрактный пример некоего инф.сообщения, которое может трактоваться неоднозначно.


> Трафик между парами определен протоколом другим


Ну и нафих это надо - месить два протокола там где место одному ?

<код команды серверу>[<параметры команды серверу>]

В <параметры команды серверу> пиши что угодно, в т.ч. команды другого протокола, ибо серверу на них начхать  - он понимает и трактует только своикоманды.

Например,

Команда - SendCmdToPeer
Параметры: PeerID, CmdCode, CmdParams

Команда - RecvResponceFromPeer
Параметры: PeerID, CmdRequestID


Сергей М.   (2009-09-17 17:01:00) [40]


> Процедуры подключения и отключения клиентов используют один
> и тот же массив, что будет когда неск клиентов столкнутся
> на одном и том же массиве, в том смысле то есть что он им
> обоим будет нужен сразу?


Грабли будут.
Доступ к потоконебезопасному ресурсу обязателен к синхронизации.


> что будет если кто-то из клиентов соберется что-то отправить,
>  в то время как УЖЕ будет работать процедура Send вызванная
> предыдущим клиентом?


Этот "кто-то" застрянет на LockList до тех пор, пока предыдущий "кто-то" не вызовет UnlockList.


Страницы:   1 2 3 4 5 6 7 8

Наверх

Титульная страница Поиск, карта сайта Написать письмо