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

Вниз

TIdCmdTCPServer   Найти похожие ветки 

 
Zalm ©   (2009-08-31 13:14) [0]

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


 
DimaBr ©   (2009-08-31 13:42) [1]

Внимание! Здесь обсуждаются вопросы, связанные с разработкой компонентов, редакторов свойств, редакторов компонентов и экспертов IDE.
Вопросы по поиску и использованию готовых компонентов, редакторов или экспертов являются нарушением тематики и могут быть удалены.


 
Сергей М. ©   (2009-08-31 13:49) [2]

Зависит от версии Инди


 
Zalm ©   (2009-08-31 14:58) [3]

Извиняюсь перед админами.

Сергей, версия 10


 
Медвежонок Пятачок ©   (2009-08-31 15:00) [4]

и что бы узнать его адрес там и тд?

Адрес и тд узнавать не надо. Он уже есть в сессии подключенного клиента


 
Сергей М. ©   (2009-08-31 15:14) [5]


> Zalm


У любого наследника TIdCustomTCPServer, каковым является и TIdCmdTCPServer, есть публичное св-во Contexts, представляющее собой потокозащищенный список потоков, в контекстах каждого из которых исполняется каждое из активных соединений с клиентами.

Каждый из элементов этого списка есть объект класса TIdPeerThread, у которого есть объектное св-во Connection, со всеми вытекающими)


 
Zalm ©   (2009-08-31 16:16) [6]

как раз таки я не заметил что бы из COnnection что-то вытикало, я его видел, но ничего конкретного из него мне получить неудалось


 
Медвежонок Пятачок ©   (2009-08-31 16:22) [7]

чтобы вытекание было заметным надо после коннекшена поставить точку и подождать подсказки иде


 
Сергей М. ©   (2009-08-31 16:25) [8]

Да уж, слона-то ты и не приметил)

А справка, надо понимать, тоже молчит ?


 
Zalm ©   (2009-08-31 16:39) [9]

"Server.Contexts" вот тут ниче нет явно

"Server.Bindings.Items[0].Handle" вот так можно что-то добиться, но тут УЖЕ надо знать индекс подключения, да и адрес не узнать....

а справки у меня нету)


 
Медвежонок Пятачок ©   (2009-08-31 16:40) [10]

мало точек поставил


 
Медвежонок Пятачок ©   (2009-08-31 16:41) [11]

да и адрес не узнать....

Интересно, что ты будешь делать, если узнаешь этот адрес.


 
Сергей М. ©   (2009-08-31 16:43) [12]


> "Server.Contexts" вот тут ниче нет явно


Что значит "нече нет явно" ?


> Server.Bindings


Это из другой оперы, к клиентским коннектам оно отношения не имеет.


> справки у меня нету


Мыши сгрызли ?)

Коли нету - купи, найди, укради.
Без справки ничего путного не получится - так и будешь тыкаться как слепой котенок)


 
Anatoly Podgoretsky ©   (2009-08-31 16:56) [13]

> Сергей М.  (31.08.2009 16:43:12)  [12]

А не умрет ли он скорее со справкой, ведь речь про ИНДИ


 
Сергей М. ©   (2009-08-31 16:59) [14]


> Anatoly Podgoretsky ©   (31.08.09 16:56) [13]


Ну дык еще и исходники всегда перед носом)
Довольно сложно сыграть в ящик, имея справку+исходники ..


 
Zalm ©   (2009-08-31 17:04) [15]

примеры у меня ткоа на 9-ю версию есть, там иначе всё написано.


 
Сергей М. ©   (2009-08-31 17:10) [16]

Скачай для 10-ки, в чем проблема ?
Заодно и справку скачай.


 
Медвежонок Пятачок ©   (2009-08-31 17:33) [17]

и все же загадка. зачем ему понадобился адрес клиента.


 
Zalm ©   (2009-08-31 17:46) [18]

да адрес клиента не при чем, это я просто сказал что например как узнать.
Главное как клиента идентифицировать что бы потом знать кто есть кто...


 
Медвежонок Пятачок ©   (2009-08-31 17:56) [19]

коннекшен - это и есть "кто"


 
Zalm ©   (2009-08-31 18:27) [20]

угу, если бы я писал через TServerSocket  я бы не задавал таких тупых вопросов.

Ну вот разве что это что-то дельное AContext.Connection.Socket.Binding.Handle;
и адрес там можно узнать.
Тока пользы никакой для меня, в Server.Contexts я так и не нашел куда можно этот значение приспособить...
Тока в Server.Bindings.BindingByHandle(HND).SendTo(); можно пихнуть... и то не получилось:(

а примеры на 10-Ю версию не могу найти((


 
Медвежонок Пятачок ©   (2009-08-31 18:29) [21]

Дядя, в метод OnExecute сервера тебе передано нечто.
Нечто это бывает разным в разных версиях инди.
Вот это нечто и есть то что тебе надо. А так же все что вложено в этот тип.


 
Медвежонок Пятачок ©   (2009-08-31 18:32) [22]

для десятки это будет так:
IdCmdTCPServer1Execute(AContext: TIdContext);

вот этот контекст и есть то, что чего ты весь день ищешь


 
Zalm ©   (2009-08-31 19:01) [23]

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


 
Сергей М. ©   (2009-08-31 20:50) [24]


> мне Execute не надо, я там ничего не пишу


А куда ты денешься с подводной лодки ?
Придется писать.


> как записать в массив что-то конкретное из


Не надо ничего никуда "пихать" - все уже давным-давно "напихано".

В списке Connections.LockList каждый элемент - это TIdPeerThread.
У TIdPeerThread есть объектное св-во Connection: TIdSocketHandle
У объекта TIdSocketHandle есть св-ва PeerIP и PeerPort - адрес и порт клиента. Эта комбинация всегда уникальна, и этого достаточно для однозначной идентификации клиента.
Кр.того, у объекта TIdSocketHandle есть send/recv-методы для коммуникации с клиентом.


 
Zalm ©   (2009-08-31 22:55) [25]

эх так и знал что вся подстава в этом LockList ((( я его открыл посмотрел и забил, ибо не показалось что как-то с сервером связано.

А зачем обязательно в Execute писать?

Спасибо большое, щас пойду пробовать.


 
Zalm ©   (2009-09-01 03:35) [26]

Я наверное что-то не понимаю... но у меня нельзя так сделать из любого места. Вот допустим я знаю порт и адрес, как вы сказали,
Потом отсылаю в процедуру, адрес и порт, а когда хочу написать в процедуре Server.Connections то такого нет, есть только Server.Contexts.LockList а в лок-листе нет опять же свойства ни сокетов ни Connections...  опять я чего-то не понял? :(


 
Медвежонок Пятачок ©   (2009-09-01 07:58) [27]

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

а на самом деле там у тебя там дрова лежат.

ps
для обмена между сервером и клиентом нужно стрго следовать какому-то стандартному протоколу, либо придумать свой протокол и следовать ему.


 
Сергей М. ©   (2009-09-01 10:05) [28]


> зачем обязательно в Execute писать?


А ты и в Execute не напишешь.
Execute вызывается только если у сервера список CommandHandlers пуст, а он у тебя заведомо не пуст, ибо нафих тогда нужен TidCmdTCPServer ?
Ты пойми главное - TidCmdTCPServer не предназначен для выкрутасов задуманного тобой вида, он заточен и призван работать в режиме "команда клиента -> ответ сервера как результат выполнения этой команды". На то как раз ComandHandler"ы у него и существуют.


 
Zalm ©   (2009-09-01 21:42) [29]

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


 
Сергей М. ©   (2009-09-01 22:10) [30]


> как лучше можно было бы сделать


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


 
Zalm ©   (2009-09-01 23:13) [31]

эх.. а конкретнее?
что сложного сделать сервер котоый будет просто текст перебрасывать?
ему же ничего не надо трогать, получил, передал дальше, и всё.
Как я понял уже через TIdCmdTCPServer это не очень удобно делать.


 
Сергей М. ©   (2009-09-02 09:11) [32]


> что сложного сделать сервер котоый будет просто текст перебрасывать?


А нашиша тогда выбрал TIdCmdTCPServer, если требуется "просто текст перебрасывать" ? Почекму не TIdTCPServer ? И чем так уж не угодил тот же самый TServerSocket, тем более что там для тебя "проще всё, ну или понятней" ?


> а конкретнее?


Вот сейчас мы с тобой "разговариваем" при использовании протокола информационного обмена HTTP.
А ты разработал свой протокол ?)


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

Я знаю что такое HTTP и как работает...
Если это можно назвать "разработал", то можно и так, но только не для обмена с сервером "пересылки", а с конечными точками.
TServerSocket мне не нравится так придется все потоки в ручную писать и много вобще придется писать.
А на TIdTCPServer думаю проще будет, он и потоки сам создает же, и всё лучше... так что попробую через него.

Еще вопрос такой мб сторонний немного, к этой теме относится только тем что тоже работа с сетью. Можно Как-то закосить сервер под сервер аси? что бы например конектится не к login.icq.com, а например к моему сервру, и что бы он клиенту контакт лист выдал и мог читать что этот клиент отправит на сервер? и не более. Больше ничего серверу не требуется кроме как выдать конаткт лист с заранее вписанными на сервер контактами, и читать что этим контактам будет слать клиент. То есть есть один сервер и один клиент.. ну думаю вы поняли задачу..)


 
Сергей М. ©   (2009-09-02 17:31) [34]


> но только не для обмена с сервером "пересылки", а с конечными
> точками


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


> TServerSocket мне не нравится так придется все потоки в
> ручную писать


В смысле ?


> Можно Как-то закосить сервер под сервер аси?


Можно.


 
Медвежонок Пятачок ©   (2009-09-02 18:35) [35]

что сложного сделать сервер котоый будет просто текст перебрасывать?

не сложно. сложно написать клиента который понял бы все перебрасываемое ему.
хотя тоже не сложно (если самому себе не рыть ям)


 
Zalm ©   (2009-09-02 18:52) [36]

я знаю как всё написать, просто пока не определился точно к компонентом.

Читая протокол я не понял какие команды сначала надо слать с сервера клиенту когда он подключится тока... я подключался с телефона к серверу, он подключается и молчит и чего-то ждет... где можно прочитать коротко какая последовательность компанд друг другу дожна быть что бы они подключились? Подскажете?


 
Сергей М. ©   (2009-09-02 22:18) [37]


> Читая протокол


Как можно читать то, что ты еще не написал ?)


> какие команды сначала надо слать с сервера клиенту


А что, клиент нуждается в каких-то командах ?
Нахрена, спрашивается, тогда нужен сервер, если клиенты готовы исполнять его прихоти ?)


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


Никакая.
Ты же сам утверждаешь, что якобы "подключался с телефона к серверу", при этом ни ты серверу, ни сервер тебе не посылал никаких "команд")
Чудеса ?)


 
Anatoly Podgoretsky ©   (2009-09-03 09:10) [38]


> Ну дык еще и исходники всегда перед носом)

Ну ты и садист.


 
Zalm ©   (2009-09-06 05:14) [39]

ох... вернулся к этой тему.. что-то я никак не пойму:( у меня не получается никак отправить кому-то что-то за пределы его потока.

можете пожалуйста если вам не сложно показать кусок конкретного кода как отправить кому-то что-то не из его потока?
Я был бы очень благодарен


 
Zalm ©   (2009-09-06 16:47) [40]

отправить через TidTCPServer, забыл уточнить


 
Сергей М. ©   (2009-09-06 16:50) [41]


> у меня не получается


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


 
Сергей М. ©   (2009-09-06 16:51) [42]


> отправить через TidTCPServer, забыл уточнить


Хоть через луну !

Ход своей мысли продемонстрируй ..


 
Zalm ©   (2009-09-06 21:13) [43]


unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer, Buttons,
 idContext;

type
 TForm1 = class(TForm)
   Server: TIdTCPServer;
   procedure ServerConnect(AContext: TIdContext);
   procedure ServerExecute(AContext: TIdContext);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

 _Pack = Record
         Primary_handle : Cardinal;
         Secondary_handle : Cardinal;
         Primary_index : string[8];
         Secondary_index : string[8];
        End;

 {функция для того что бы составить пару из подключений}
 Function Connect_to_Clients( Handle : cardinal; index : string):boolean;
 {получение хэндла "соседа" пары, отправили свой handle, в ответе     получили его handle}
 Function GetHandleByHandle(Handle : cardinal):Cardinal;
 { "переброс" команд, отправляем свой handle, и что хотели отправить "соседу"}
 Procedure Transfer(handle : cardinal; str: string);

var
 Form1: TForm1;
 Pack : _Pack;
 Clients : Array of _Pack;
 Clients_count : integer;

implementation

{$R *.dfm}

procedure TForm1.ServerConnect(AContext: TIdContext);
var
str : string;
begin
AContext.Connection.Socket.WriteLn("Welcame"+#13+"Index[8]: ");
Str:=AContext.Connection.Socket.ReadLn();
if length(str)<>8 then
 begin
  AContext.Connection.Socket.WriteLn("Error length index");
  AContext.Connection.Disconnect;
 end
else
 begin
  if Connect_to_clients(Acontext.Connection.Socket.Binding.Handle,str) then
   begin
    Acontext.Connection.Socket.WriteLn("Start transfer");
   end
  else
   begin
    Acontext.Connection.Socket.WriteLn("Error registration");
    AContext.Connection.Disconnect;
   end;
 end;
end;

Function Connect_to_Clients( Handle : cardinal; index : string):boolean;
var
i : integer;
register_ : boolean;
begin
Result:=false;
for i:=0 to Clients_count-1 do
 begin
  if ((Clients[i].Primary_index=index)or(Clients[i].Secondary_index=index)) then
   begin
    if Clients[i].Primary_index=index then
     begin
      Clients[i].Secondary_handle:=Handle;
      Clients[i].Secondary_index:=index;
      result:=true;
      exit;
     end;
    if Clients[i].Secondary_index=index then
     begin
      Clients[i].Primary_handle:=Handle;
      Clients[i].Primary_index:=index;
      result:=True;
      exit;
     end;
   end;
 end;
inc(clients_count);
SetLEngth(Clients,Clients_count);
Clients[Clients_count-1].Primary_handle:=handle;
Clients[Clients_count-1].Primary_index:=Index;
Result:=True;
end;

procedure TForm1.ServerExecute(AContext: TIdContext);
var
msg : string;
i : integer;
begin
msg:=AContext.Connection.Socket.ReadLn();
if msg="\handle\" then
 begin
  AContext.Connection.Socket.WriteLn(IntTOStr(AContext.Connection.Socket.Binding.H andle));
  exit;
 end;
if msg="\clients\" then
 begin
  for i:=0 to CLients_count-1 do
   begin
    AContext.Connection.Socket.WriteLn(
    "-----------------"+#13+"Couple "+IntToStr(i+1)+#13+
    "PH: "+IntToStr(Clients[i].Primary_handle)+#13+
    "PI: "+Clients[i].Primary_index+#13+
    "SH: "+IntToStr(Clients[i].Secondary_handle)+#13+
    "SI: "+Clients[i].Secondary_index);
   end;
   AContext.Connection.Socket.WriteLn("Done. "+IntToStr(Clients_count)+" couples.");
  exit;
 end;
if msg="\couples\" then
 begin
  AContext.Connection.Socket.WriteLn(INtToStr(Clients_count)+" couples.");
  exit;
 end;
if msg="\GetHandleByHandle\" then
 begin
  AContext.Connection.Socket.WriteLn(IntToStr(GetHandleByHandle(AContext.Connectio n.Socket.Binding.Handle)));
 end;
Transfer(AContext.Connection.Socket.Binding.Handle,msg);
end;

Procedure Transfer(handle : cardinal; str: string);
var
_handle : cardinal;
begin
_handle:=GetHandleByHandle(handle);
{...по идее тут отправка str подключению с известным нам _handle,
 это и есть товарищ из пары, вот только как отправить таким спобом
 этого я не знаю..:( }
end;

Function GetHandleByHandle(Handle : cardinal):Cardinal;
var
i : integer;
begin
result:=0;
for i:=0 to Clients_count-1 do
 begin
  if Clients[i].Primary_handle=handle then
   begin
    result:=Clients[i].Secondary_handle;
    exit;
   end;
  if Clients[i].Secondary_handle=handle then
   begin
    Result:=Clients[i].Primary_handle;
    exit;
   end;
 end;
end;

end.


вот, вроде как бы всё работает, но до определенного затыка в процедуре Transfer.


 
Сергей М. ©   (2009-09-07 09:01) [44]

Тихий ужас..

Хендлы какие-то куда-то отправляются ..

Ты в состоянии изложить формальное описание разработанного тобой протокола инф.обмена между клиентами и сервером ?


 
Сергей М. ©   (2009-09-07 10:13) [45]

За каким тебе понадобились хендлы, если у тебя есть список уникальных объектов IdTCP.Server.Connections, каждый из которых отражает контекст соединения сервера с одним из его активных клиентов ?


 
Zalm ©   (2009-09-07 12:52) [46]

да что есть? ничего там нет, просил же показать то о чем вы всё время говорите, так вы не можете.
Зачем вам всё время нужен этот протокол я никак не понимаю, у меня проблема совсем в другом.


 
Zalm ©   (2009-09-07 12:57) [47]


> если у тебя есть список уникальных объектов IdTCP.Server.
> Connections

У вас может быть и есть, а у меня нету. есть только Server.Contexts в котором есть LockList в котором уже я ничего не нашел.
Вот просил же хоть что-то показать конкретное, а вы мне только наводящие вопросы задаете, которые ни на что не наводят меня(


 
Сергей М. ©   (2009-09-07 13:13) [48]


> Зачем вам всё время нужен этот протокол я никак не понимаю


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

Пойми, наконец, что без формализованного прикладного протокола инф.обмена ничего путного у тебя не получится. Любую сколь-либо серьезную сетевую разработку следует начинать с листа бумаги и авторучки, а не со слепого тыканья в компонентах.


> у меня проблема совсем в другом


Не надо себе их, проблемы эти, создавать, тогда и не придется их потом героически преодолевать.

Взять хотя бы элементарное, о чем я у тебя уже спросил в [45] ..


 
Сергей М. ©   (2009-09-07 13:21) [49]


> у меня нету. есть только Server.Contexts


Да ну какая разница ?
пусть будет не Connections, а Contexts - суть свойства от  этого не меняется.


> LockList в котором уже я ничего не нашел


Что и где ты искал из того что не нашел ?


 
Сергей М. ©   (2009-09-07 13:23) [50]


> вопросы задаете, которые ни на что не наводят меня


Это печально. Очень.


 
Anatoly Podgoretsky ©   (2009-09-07 13:24) [51]

> Zalm  (07.09.2009 12:57:47)  [47]

Так вопросы задаются, потому что от тебя не поступило полной информации,
если не ты, то мы.


 
Сергей М. ©   (2009-09-07 13:36) [52]


> Zalm


Ты вообще осознаешь, что работу с каждым из своих клиентов IdTCP-сервер осуществляет в отдельном дополнительном треде ?
Судя по

> У TServerSocket было проще всё, ну или понятней

ты обязан это осознавать, ибо в режиме stThreadBlocking TServerSocket работает точно так же как и IdTCP-сервер.
Если осознаешь, то почему не выполняешь обязательную синхронизацию доступа к потоконебезопасным ресурсам, таким как, например, массив Clients, переменную Clients_count ?


 
Zalm ©   (2009-09-07 13:39) [53]

Ну нету никакого протокола. В коде же видна идея как осуществляется обмен. При подключении "зарегистрировали" клиента, и всё, потом другой клиент подключается, такая же процедура, если они вводят один и тот же индекс, они получаются в паре, и сервер сразу передает между ними абсолютно всё что шлют (текст). Клиенты к этому серверу-посреднику обратиться никак не могут, ибо незачем.


> За каким тебе понадобились хендлы, если у тебя есть список
> уникальных объектов IdTCP.Server.Connections, каждый из
> которых отражает контекст соединения сервера с одним из
> его активных клиентов ?

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


> > LockList в котором уже я ничего не нашелЧто и где ты искал
> из того что не нашел ?

Ну вот Server.Contexts.LockList  а дальше что? есть Items[index:integer]:pointer, это единственное что вызывает какое-то внимание, но сделать тоже ничего не получается с этим. Так что чем может помочь этот LockList я не понимаю, и вы подсказать не можете.

видел кусок из примера для инди 9


List := tcpServer.Threads.LockList;
 try
   for Count := 0 to List.Count -1 do
   try
     TIdPeerThread(List.Items[Count]).Connection.WriteLn(Msg);
   except
     TIdPeerThread(List.Items[Count]).Stop;
   end;
 finally
   tcpServer.Threads.UnlockList;
 end;

Они себе в переменную типа TList копируют себе этот LockList и рассылают всем сообщение. ТОлько что такое  TIdPeerThread я не знаю, у меня такого нет. У них есть еще IdThreadMgrDefault1: TIdThreadMgrDefault; это в описании, тоже не знаю что это, у меня ткого нет.
Вобщем жаль что не хотите ничего конкретного подсказать.


 
Zalm ©   (2009-09-07 13:45) [54]


> Ты вообще осознаешь, что работу с каждым из своих клиентов
> IdTCP-сервер осуществляет в отдельном дополнительном треде
> ?

это да, это я знаю.
> почему не выполняешь обязательную синхронизацию доступа
> к потоконебезопасным ресурсам, таким как, например, массив
> Clients, переменную Clients_count ?

не знаю, я такого раньше не делал, проблем как мне казалось из-за этого не было. да и как это синхронизацию я не знаю, я с этим не сталкивался к сожалению


 
Медвежонок Пятачок ©   (2009-09-07 13:48) [55]

Ну нету никакого протокола.  

У тебя ничего не получится.


 
Сергей М. ©   (2009-09-07 13:51) [56]


> Ну нету никакого протокола


Ты прикидываешься или где ?

Как это "нету" ?

А это, к примеру, что по-твоему


> "Welcame"


?

Почему именно "велцаме" у тебя фигурирует, а не "Здарофф, чувак ! Ет я, сервер, с тобой разговариваю" ?


 
Сергей М. ©   (2009-09-07 13:57) [57]


> Ну вот Server.Contexts.LockList  а дальше что?


Ну и что толку тебе объяснять про "дальше что", если межпоточная синхронизация и защита ресурсов для тебя что новые ворота ?


 
Сергей М. ©   (2009-09-07 14:04) [58]


> что такое  TIdPeerThread я не знаю, у меня такого нет


В 10-ке элементами этого списка явл-ся объекты класса TIdContext


 
Медвежонок Пятачок ©   (2009-09-07 14:04) [59]

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


 
Сергей М. ©   (2009-09-07 14:12) [60]


> про ресурсы ему еще рано


Тогда и делать ему пока нефига в индейских серверах. Не по сеньке шапка.
Есть TServerSocket, есть stNonBlocking - там ему "было проще всё, ну или понятней".
Какого лешего ему понадобилось лезть в индейские мультипоточные блокирующие дебри - до сих пор не понятно.
Было бы хотя бы вразумительное обоснование выбора Инди - был бы тогда и стимул вдалбливать ему про синхронизацию и прочую мультипоточную требуху. А так  - что о стенку горох)


 
Медвежонок Пятачок ©   (2009-09-07 14:57) [61]

правильная конфигурация:
сервер постоянно читает запросы клиентов.
получив запрос клиента, отправляет ему ответ, затем снова читает/ждет следующий запрос.

рассылка всем клиентам сообщения по инициативе сервера:
сервер получает текст сообщения от администратора и ничего никуда не посылает. Запоминает его и ждет, когда клиент запросит " А нет ли для меня какого-нить сообчения?"
Получив подобный запрос клиента, сервер отдаети ему сообщение прямо в обработчике команд, без всяких локлистов и прочей ерунды.


 
Сергей М. ©   (2009-09-07 15:09) [62]


> без всяких локлистов и прочей ерунды


В мультипоточном сервере без lock-тряхомудии вряд ли обойтись)
Другой вопрос - она нада ли автору, мультипоточность та самая ..
Впрочем, он и сам не знает.


 
Медвежонок Пятачок ©   (2009-09-07 15:14) [63]

локлист нужен для операций по инициативе сервера.
допустим что клиент у нас "событийный", а сервер "процедурный".
то есть все построено задом наперед.
тогда да.
лочим список коннектов, засылаем клиентам мессаджи и разлочиваем.
если же сервер посторить как строят его нормальные герои (ожидание запроса->обработка->посылка ответа ), то лочить ничего не надо.
все происходит либю в OnExecute, либо в диспетчерах прикладных команд.

Но нах юный друг хочет чтобы и сервер и клиент были одновременно и сервером им клиентом.


 
Сергей М. ©   (2009-09-07 15:34) [64]


> лочить ничего не надо


Ну как же не надо ?


> все происходит либю в OnExecute, либо в диспетчерах прикладных
> команд


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


 
Медвежонок Пятачок ©   (2009-09-07 15:45) [65]

Ну это само собой разумеется.
Но я-то про Среадс.ЛокЛист говорил конкретно.
Точнее про то, что он почти никогда не нужен правильному серверу.


 
Сергей М. ©   (2009-09-07 15:47) [66]


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


С этим солидарен.


 
Zalm ©   (2009-09-07 17:05) [67]

правильный сервер... я бы вобще не назвал то что мне нужно сервером.
Вобщем ладно, спасибо вам за участие в теме, понял что помощи не будет


 
Медвежонок Пятачок ©   (2009-09-07 17:17) [68]

фигасе заявки. "помощи не будет".


 
Сергей М. ©   (2009-09-07 17:18) [69]


> я бы вобще не назвал то что мне нужно сервером


Обзови его хоть горшком - как он был сервером, так он им и останется.
Его задача - обслуживать (to serve) клиентов, если они не в состоянии сами себя обслужить.


> помощи не будет


Тебе уже 68 постов только и делают, что помогают, а ты все не внемлешь.


 
Сергей М. ©   (2009-09-07 17:30) [70]


> если бы я писал через TServerSocket  я бы не задавал таких
> тупых вопросов


Глубоко в этом сомневаюсь.
Были бы другие, но не менее тупые.


 
Zalm ©   (2009-09-07 17:48) [71]

Server.Bindings.BindingByHandle(handle : cardinal)

а это что делает?


 
Zalm ©   (2009-09-07 17:51) [72]

вот что сложного ответить на вопрос как отправить клиенту строку зная либо хендл, либо его адрес, либо его индекс подключения?)


 
Zalm ©   (2009-09-07 18:07) [73]

что вобще сложного в том сервере который мне нужен? та же структура что и у сервера аси, получил передал сразу вот и всё...


 
Медвежонок Пятачок ©   (2009-09-07 18:10) [74]

получил передал сразу вот и всё...

не сразу, а только по запросу того, кому это предназначалось.


 
Медвежонок Пятачок ©   (2009-09-07 18:14) [75]

Вот я клиент твоей аси.
И Сергей М. тоже клиент.

Я нажимаю кнопку и запрашиваю инфо о контакте Сергея М.
В это время он мне шлет сообщение "Превет Медвет"
Сервер его получает и тут же сразу же мне его шлет.
А я в это время отправил запрос о его профиле и жду его.
А в ответ мне вместо данных его профиля приходит "Превет Медвет".
Я (точнее твой чудо-клиент аси) при этом в полной уверенности что:
1. Получил не сообщение, а инфу о профиле Сергея М
2. Мне не пришло текстовое сообющение от Сергея М

дальше разжевывать надо?


 
Zalm ©   (2009-09-07 18:23) [76]

ася что ли сидит и спрашивает у сервера есть ли для неё сообщения?

вобще один товарищ посоветровал не возится с таким сервером "посредником" а связать компы не имеющие выделенных адресов через VPN. Тока я еще не совсем дочитал что это такое... так что пойду читать, мб и не нужен будет такой сервер...


 
Медвежонок Пятачок ©   (2009-09-07 18:27) [77]

ася что ли сидит и спрашивает у сервера есть ли для неё сообщения?

Ты лучше спроси как она вообще получает сообщения ничего не запрашивая (якобы) и ничего не читая (якобы).


 
Медвежонок Пятачок ©   (2009-09-07 18:29) [78]

Хотя этот вопрос лишний.
Ты попробуй сначала выкрутится из ситуации, что описана у меня в [75].

Когда в ответ на запрос информации о контакте приходит не инфа о контакте, а "Превет Медвет".


 
Zalm ©   (2009-09-07 18:34) [79]

ну а что там выкручиться, сложности никакой.
например синтаксис для собщения MSG_<сообщение>, а для инфы INFO_<инфа>, и какой тут напряг? придет себе сообщение, будет оно как сообщение, а инфу по-прежнему ждем


 
Сергей М. ©   (2009-09-07 18:38) [80]


> Zalm ©   (07.09.09 17:51) [72]


А что ты хотел видеть в кач-ве ответа на этот вопрос ?


> а это что делает?


"Это" возвращает binding-структуру с интересующим значением поля handle.


> та же структура что и у сервера аси, получил передал сразу
> вот и всё


Это тебе "сервер ася" сказал ?
Или ты изучил документацию ?


> вот что сложного ответить на вопрос как


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


 
Zalm ©   (2009-09-07 18:44) [81]


> Это тебе "сервер ася" сказал ?Или ты изучил документацию
> ?

ну нет, я в начале второго курса писал подобие аси... в итоге всё работало нормально. всё передавалось и принималось.


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

почему это? это голословно))) не думаю что это мне не принесет никаких результатов... так что думаю вы ошибаетесь


 
Медвежонок Пятачок ©   (2009-09-07 19:00) [82]

procedure TForm1.Button1Click(Sender: TObject);
var List : TList; i : integer;
begin
try
 List := IdCmdTCPServer1.Contexts.LockList;
 for i := 0 to Pred(List.Count) do
  with TIdContext(List[i]) do
   begin
    if (Connection.Socket.Binding.PeerIP = "1.2.3.4") and (Connection.Socket.Binding.PeerPort = 1234) then
     TIdContext(List[i]).Connection.Socket.Write("привет");
   end;
finally
 IdCmdTCPServer1.Contexts.UnlockList;
end;
end;


 
Сергей М. ©   (2009-09-07 19:31) [83]


> я .. писал ..


Я понимаю, что ты писатель, а не читатель.


> не думаю что это мне не принесет никаких результатов


Ты вообще не думаешь. Вероятно, не спрособен думать.
Иначе давным бы давно реализовал кучу данных тебе подсказок.


> Медвежонок Пятачок ©   (07.09.09 19:00) [82]


Зря.
Клиент скорее мертв.
К тому он ханделЯми озабочен, а ты ему пир:порт)


 
Zalm ©   (2009-09-10 20:25) [84]

Сергей что ж вы злой такой?)

Спасибо большое Пятачок)


 
Zalm ©   (2009-09-11 02:26) [85]

А TidTCPServer имеет какие-то функции\процедуры для подсчета входящего\исходящего трафика? или только руками можно посчитать?
Подскажите пожалуйста)


 
Сергей М. ©   (2009-09-11 08:29) [86]

Тотальный подсчет трафика не предусмотрен.
Однако есть события TIdTCPConnection.OnWork , TIdIOHandler.OnWork - их можно приспособить для тотального подсчета прикладного трафика.


 
Zalm ©   (2009-09-11 17:37) [87]

аа... Спасибо Сергей


 
Zalm ©   (2009-09-12 02:58) [88]

такая не приятная ситуация у меня наблюдается...
дело такое, подключаюсь я с телефона к своему серверу, и клиент подключаю с компа.. если какое-то, именно какое-то не определенное (время не определял) время ничего не слать, то спустя "ЭТО ВРЕМЯ" если что-то написать первая команда просто где-то теряется, а если сразу же за этой командой отправить что-то то всё опять хорошо... словно эта потерянная команда оживляет сервер или клиент парный... вы знаете почему такое может быть?
детального анализа еще не делал где теряется команда и куда доходит.. сначала думал спросить у вас с чем это может быть связано..
может TerminateWaitTime 5000 на сервере дает такой эффект? или надо сделать какой-то "keep alife"?


 
Сергей М. ©   (2009-09-14 08:21) [89]

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


 
Zalm ©   (2009-09-14 13:33) [90]

какая может быть ошибка предположительно? как я полнял сервер работает нормально, если пара не полная, то он и через час ответит что не кому отсылать что-то, его не надо "оживлять", а вот с клиентом похоже проблема.
Может время ReadTimeout поменять? там -1 стоит


 
Сергей М. ©   (2009-09-14 14:18) [91]


> какая может быть ошибка предположительно?


Какая угодно. И где угодно.
Но факт, что это ошибка в твоем коде.


 
Медвежонок Пятачок ©   (2009-09-14 14:56) [92]

если что-то написать первая команда просто где-то теряется

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

PS
надо было слушать дядей, которые говорили что первым делом следует разработать протокол обмена.


 
Сергей М. ©   (2009-09-14 15:05) [93]

Не царское это дело - разработка протокола.
Быстрей бы "пАры"  "окучить"


 
Zalm ©   (2009-09-14 20:21) [94]


> Не царское это дело - разработка протокола.Быстрей бы "пАры"
>  "окучить"

Да Сергей, сколько можно уже, вот какой там должен быть протокол обмена? вот хоть пример предложите.


> если что-то написать первая команда просто где-то теряется

она теряется не сразу, если что-то всё время слать то всё нормально, она теряется спустя какое-то время если ничего е слать...
Так что лучше ридэлен не использовать? просто рид?


 
Сергей М. ©   (2009-09-14 20:33) [95]


> вот хоть пример предложите


Примеров - как грязи.
Возьми за пример хотя бы тот что у тебя прямо перед носом - HTTP

http://ru.wikipedia.org/wiki/HTTP


 
Zalm ©   (2009-09-15 01:17) [96]

это как я давно и думаю команды всякие сделать и как надо отвечать на них? у меня это есть


 
Сергей М. ©   (2009-09-15 08:59) [97]


> команды всякие сделать
> как надо отвечать на них?


Это у тебя хотелось бы спросить - ты же разработчик, за тебя это никто не сделает)

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


> у меня это есть


Ну так приведи в божеский и представь здесь имеющееся у тебя, в чем проблема-то ?
Великий секрет что ли


 
Zalm ©   (2009-09-16 01:17) [98]

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

Index[10]
это означает что нужно ввести идентификатор, по которому составляется пара. После того как идентификатор получен сервер шлет команду
srd (да, тупая, но ничего не пришло на ум другого, рашифровывается как server ready)
после этой команды сервер перестает обрабатывать то что получает, а сразу кидает второму члену пары, если таковой имеется, если нет то сервер присылает команду
No send
вот и всё.
Есть еще всякие командочки для обслуживания, типа проверить сколько клиентов щас подключено, сменить ключ, показать адрес там и тд, думаю вас это уже не интересует потому что на ход работы это не влияет уже


 
Сергей М. ©   (2009-09-16 08:42) [99]


> надо ввести ключ


Что за "ключ" ?
Чем "ключ" не команда ?
Где описание формата этой команды ?


> если ключ не верный


Клиент сам догадывается, что ключ не верный ?
Или же сервер в ответ на это возвращает нечто, информирующее клиента о валидности или невалидности "ключа" ?


> то сразу клиент отключается


А если не отключится ? Если продолжит инф.обмен ?
Что делать серверу с этим "невалидным" соединением ?


> Index[10]


Это чего, строка ? Что это означает ?
Почему не Index[5555555] ?
И зачем числовые параметры 5555555 передавать в строковом, а не в бинарном виде ?


> нужно ввести идентификатор, по которому составляется пара


Кому "нужно" ? Что значит "ввести" ? Где и куда его "ввести" ?


> сервер шлет команду
> сервер присылает команду


Ты опять за своё ?) Какая еще "команда" ? Ну сколько можно, а ?
Командует клиент, а не сервер !
Сервер получает команды от клиентов (а не клиенты получают команды от сервера), обрабатывает их и возвращает клиентам результаты  обработки команд, а не команды !


> Есть еще всякие командочки для обслуживания


> не интересует потому что на ход работы это не влияет уже


Это как это не влияет ?!

Каким, спрашивается, образом клиент получит результаты обработки посылаемых им "еще командочек", если ты утверждаешь, что


> после этой команды сервер перестает обрабатывать то что
> получает, а сразу кидает второму члену пары, если таковой
> имеется


??

Согласно этому выходит, что клиент посылает "еще командочки для обслуживания", а серверу на их исполнение уже начхать - он прямиком посылает эти "еще командочки" тому самому "второму члену пары, если таковой имеется".

Одним словом, курам на смех такой протокол)

Переделывай, доводи до ума.


 
Сергей М. ©   (2009-09-16 08:57) [100]

Кстати, а зачем понадобилось участие сервера в инф.обмене между "парами" ?

Почему участники "пары" не могут или не имеют права установить соединение друг с другом напрямую (P2P = Peer To Peer), как это реализуется в ряде известных программных продуктов схожего назначения ?

Этому есть вразумительное объяснение ? Чем продиктовано такое требование - обмен только через твой сервер-посредник ?


 
Zalm ©   (2009-09-16 18:26) [101]


> > надо ввести ключ
 Что за "ключ" ?Чем "ключ" не команда ?
> Где описание формата этой команды ?

нет описания, ключ это строка которая указана на сервере, вот и всё.


> > если ключ не верный

> Клиент сам догадывается, что ключ
> не верный ?Или же сервер в ответ на это возвращает нечто,
>  информирующее клиента о валидности или невалидности "ключа"
> ?


ничего не возвращает, отключает сразу и всё


> > то сразу клиент отключается
> А если не отключится ? Если
> продолжит инф.обмен ?Что делать серверу с этим "невалидным"
> соединением ?


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


> > Index[10]
>Это чего, строка ? Что это означает ?

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


> > нужно ввести идентификатор, по которому составляется пара

>Кому
> "нужно" ? Что значит "ввести" ? Где и куда его "ввести"
> ?


Нужно клиенту. Ввести значит написать и отправить на сервер.


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


так и выходит, после того как составлена пара кроме конкретных команд сервер ничего не воспринимает, или другими словами как вы сказали ему начхать на всё что он получает. Это так потому, что серверу не нужно знать что он получает и передает.
Когда сервер получает какую либо команду, он сначала проверяет нет ли такой команды из списка так сказать технических, если такой нет, то он всё что получил кидает другому клиенту, вот и вся работа сервера.
Если хотите напишите свою почту, я скажу вам адрес сервера, посмотрите как всё работает.


 
Zalm ©   (2009-09-16 18:28) [102]


> Этому есть вразумительное объяснение ? Чем продиктовано
> такое требование - обмен только через твой сервер-посредник
> ?

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

-----------

> Если хотите напишите свою почту, я скажу вам адрес сервера,
>  посмотрите как всё работает.

вернее я вам пришлю программу сервера, псмотрите как он работает


 
Сергей М. ©   (2009-09-16 20:29) [103]


> Zalm ©   (16.09.09 18:26) [101]


> ключ это строка которая указана на сервере, вот и всё
> ничего не возвращает, отключает сразу и всё


Значит "ключ" - это определенная в твоем протоколе команда, на которую сервер при получении не должен отвечать.

И всё.


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


Вот это ты и должен был указать в протоколе - при получении такой-то команды сервер немедленно разрывает соединение по своей инициативе.

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


> Ввести значит написать


Где написать ? На бумаге ?


> Когда сервер получает какую либо команду, он сначала проверяет
> нет ли такой команды из списка так сказать технических


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

Предположим, твой сервер по команде со стороковым кодом "HELP" обязан передать клиенту некую справочную инф-цию.

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

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

Как твой сервер должен будет понять, кому адресована эта строка ?
То ли это команда "HELP", адресованная самому серверу, то ли это один конец "пары" кричит другому концу "HELP" ...


> я вам пришлю программу сервера, псмотрите как он работает


У меня нет ни малейшего желания глазеть на нечто лишенное вразумительного описания протокола.


> без выделенного адреса


Что значит "без выделенного" ?
Кем и кому он, по-твоему, д.б. выделен ?


 
Сергей М. ©   (2009-09-16 21:06) [104]


> без выделенного адреса


Адрес не может быть не выделен - он обязателен для любого устройства, взаимодействующего с другими устройствами по IP.


 
Zalm ©   (2009-09-16 22:41) [105]


> Значит "ключ" - это определенная в твоем протоколе команда,
>  на которую сервер при получении не должен отвечать.

именно так))


> > Ввести значит написать
> Где написать ? На бумаге ?

Что ж вы так к словам-то всегда прям цепляетесь) всё равно где ввести, написать, или там еще какие другие варианты, набить например, тут имеется ввиду что это дело, написанное, набитое, напечатанное, надо отправить потом на сервер.


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

так и есть, только команды хелп нет и не предвидится


> Как твой сервер должен будет понять, кому адресована эта
> строка ?То ли это команда "HELP", адресованная самому серверу,
>  то ли это один конец "пары" кричит другому концу "HELP"
> ...

Да просто, сервер понимает всего 5 каманд, которые он не передаст дальше, эти все команды имеют такой синтаксис \<команда>\, если он находит знакомую команду, то он её выполняет, и парному клиенту уже не передает, если он не нашел то передает...


> > без выделенного адреса
>Что значит "без выделенного" ?Кем
> и кому он, по-твоему, д.б. выделен ?


У моего компьютера в локальной сети адрес 10,0,0,28, как вы предполагаете возможным телефону найти такой адрес среди всего интернета? Однако у нас есть сервер который (не знаю как выразить опять прицепетесь к словам) всему нашему дому обеспечивает инет, на нем и работает моя программа, в следствии чего, телефон и мой компьютер легко могут кантактировать друг с другом.


 
Сергей М. ©   (2009-09-17 09:03) [106]


> Zalm ©   (16.09.09 22:41) [105]



> Что ж вы так к словам-то всегда прям цепляетесь


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


> написать, или там еще какие другие варианты, набить например,
>  тут имеется ввиду что это дело, написанное, набитое, напечатанное,
>  надо отправить потом на сервер


И к чему это словоблудие ?
Неужели так трудно сказать "клиент отправляет серверу идентификатор" ?
Язык что ли не поворачивается ?)


> команды хелп нет и не предвидится


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


> эти все команды имеют такой синтаксис \<команда>\


Пусть в твоем протоколе имеется команда со строковым значением "Превед !".
Пусть Васе взбрендило передать Пете строку \<Превед !>\
Как твой сервер изволит поступить в этой ситуации ?
Это же знакомая ему команда и он обязан ее выполнить !
А бедный Вася сидит и ждет, когда же Петя ответит на "преведствие")
А Петя ни сном ни духом не ведает, что Вася его поприветствовал, ибо сервер по недомыслию взял да встрял в их интимный разговор)


> У моего компьютера в локальной сети адрес 10,0,0,28


По барабану какой он.
Адрес выделен.
А то что этот адрес локальный - это совсем из другой оперы.


> среди всего интернета


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


> Однако у нас есть сервер который (не знаю как выразить опять
> прицепетесь к словам) всему нашему дому обеспечивает инет,
>  на нем и работает моя программа, в следствии чего, телефон
> и мой компьютер легко могут кантактировать друг с другом


Т.е. свой сервер ты не планируешь использовать нигде кроме как именно в этих условиях ?


 
Сергей М. ©   (2009-09-17 09:16) [107]


> телефон и мой компьютер легко могут кантактировать друг с другом


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


 
Zalm ©   (2009-09-17 15:22) [108]


> Т.е. свой сервер ты не планируешь использовать нигде кроме
> как именно в этих условиях ?

он именно для этих условий и предназначен, следовательно ответ будет "да, кроме этих условий нигде не планирую"


> достаточно поднять на вашем сервере-шлюзе любой готовый
> подходящий VPN-сервис.

достаточно, но наш администратор сказал что VPN у нас нет и никогда не будет на сервере, почему, он внятно и не объяснил.


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


а какая разница? именно там и использую.


> Пусть в твоем протоколе имеется команда со строковым значением
> "Превед !".Пусть Васе взбрендило передать Пете строку \<Превед
> !>\Как твой сервер изволит поступить в этой ситуации ?

В этом случае, сервер без всяких угрызений совести передаст пете строку \<Превед !>\ потомму то команды \<Превед !>\ по протоколу он не знает, а знает команду Превед !. Если он увидит четко то что он знает, то он выполнит. Например есть команда \data\, он выполнит и не отошлет её дальше, а если написать /data/ или \data\\ то он сраже передаст их без всякого.


 
Сергей М. ©   (2009-09-17 15:56) [109]


> а какая разница?


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


> команды \<Превед !>\ по протоколу он не знает, а знает команду
> Превед !


Как это не знает ?
Цитирую твое же высказывание:

> команды имеют такой синтаксис \<команда>\


Чем строка \<Превед !>\ не команда Превед ! ?
Синтаксис соблюден, строковый идентификатор соответствует ожтидаемому..


> Например есть команда \data\, он выполнит и не отошлет её
> дальше, а если написать /data/ или \data\\ то он сраже передаст
> их без всякого


Что мешает Васе отправить Пете строку \data\ ?
Ничто не мешает.
И Петя эту самую \data\ никогда получит, ибо сервер, по твоим же словам,  распознает это сочетание последовательно идущих символов как команду.


> команды \<Превед !>\ по протоколу он не знает, а знает команду
> Превед !


Опять же, Васе взбрендило послать не \<Превед !>\, а Превед ! ..
Чем не команда, по твоим словам, ожидаемая сервером ?


> наш администратор сказал что VPN у нас нет и никогда не
> будет на сервере, почему, он внятно и не объяснил


Зато почему-то с радостью согласился разместить на сервере совершенно сырой, абсолютно не продуманный софт)


 
Zalm ©   (2009-09-17 16:51) [110]


> Зато почему-то с радостью согласился разместить на сервере
> совершенно сырой, абсолютно не продуманный софт)

Софт отвечает всем требованиям которые я к нему предъявляю)


> Что мешает Васе отправить Пете строку \data\ ?Ничто не мешает.
>  И Петя эту самую \data\ никогда получит, ибо сервер, по
> твоим же словам,  распознает это сочетание последовательно
> идущих символов как команду.

Сервер не предназначем для чата) так что никто не пришлет того что не предусмотрено... Трафик между парами определен протоколом другим (клиента, и псевдо-сервера), а в этом протоколе нет команд которые равнозначны "техническим" командам сервера)

Вобщем меня теперь больше интересует код, знаю у вас будет кучу плохих слов на счет моего кода, но всё же я тут для того что бы научиться)


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();
{----------------------------------------}
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 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);
      exit;
     end;
   end;
finally
 Form1.Server.Contexts.UnlockList;
end;
end;



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


Type
  _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;

var
 Form1: TForm1;
 Clients : _Clients;

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;



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


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


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


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


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


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


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


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


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


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


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

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

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

Например,

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

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


 
Zalm ©   (2009-09-17 17:44) [113]


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


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


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

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


 
Zalm ©   (2009-09-17 19:42) [115]

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


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

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

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


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

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


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


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

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


> Алгоритм простой:
> 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-18 08:18) [119]


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


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


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


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


 
Anatoly Podgoretsky ©   (2009-09-18 13:34) [120]


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

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


 
Zalm ©   (2009-09-18 16:52) [121]


> нельзя использовать тип 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;



 
Zalm ©   (2009-09-18 16:53) [122]


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;


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

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

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


 
Zalm ©   (2009-09-18 17:16) [124]


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

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


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

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


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


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


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


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


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


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


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

))))

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


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-19 01:30) [127]

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


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


> edit1.Text


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

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


 
Anatoly Podgoretsky ©   (2009-09-19 20:48) [129]

> Сергей М.  (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
что-нибудь слышал ?


 
Zalm ©   (2009-09-19 22:23) [130]


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

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

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

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


 
Сергей М. ©   (2009-09-21 08:31) [131]


> секции правильно или нет


С учетом того, что обращение к Edit1 не защищено - нет, не правильно.


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


Что за бред ?
finally - это finally, а except - это except.
Две разные разницы.


 
Сергей М. ©   (2009-09-21 08:42) [132]

CS.Enter;
try
.. обращение к потоконебезопасному ресурсу ..
finally
 CS.Leave;
end;


 
Zalm ©   (2009-10-28 17:36) [133]

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


 
Сергей М. ©   (2009-10-29 10:31) [134]

Куда не пишет ?
И разве он обязан куда-то что-то писать ?


 
Zalm ©   (2009-10-29 11:53) [135]

О, Сергей опять вы) Прям рад что вы мне снова отвечаете))

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


 
Dennis I. Komarov ©   (2009-10-29 12:07) [136]

Детский сад продолжается? :)

> А как мне тогда убирать не работающие подключения?

Это каких таких?


 
Сергей М. ©   (2009-10-29 12:19) [137]


> Dennis I. Komarov ©   (29.10.09 12:07) [136]


> Это каких таких?


Ну, наверно, тех, которые уборщица Тётьклава случайно оборвала орудуя шваброй)


> Zalm ©   (29.10.09 11:53) [135]
> А как мне тогда убирать не работающие подключения?


Надо обратиться к такому подключению.
При отсутствии петли подключения попытка вызова метода передачи должна привести к исключению соотв.класса.


 
Dennis I. Komarov ©   (2009-10-29 12:37) [138]


> Ну, наверно, тех, которые уборщица Тётьклава случайно оборвала
> орудуя шваброй)

Дома уборщица тетя Клава, а на программиста денег нету...


 
Zalm ©   (2009-10-29 16:05) [139]

хех... детский сад\не детский... зачем вот это всё говорить надо.


 
Dennis I. Komarov ©   (2009-10-29 16:14) [140]


> Zalm ©   (29.10.09 16:05) [139]

Ну, может совесть проснется, так не книжку какую-нить почитать, а хотя бы вопросы формулировать понятно будем...


 
Zalm ©   (2009-10-29 21:58) [141]

вот, если отправит не работающему подключение функция должна вернуть false, однако не возвращает. Или где я не правильно написал?


Function Send(ip:string;port:word;str:string):boolean;
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
      try
       TidContext(list[i]).Connection.Socket.WriteLn(str);
      except
       Result:=False;
      end;
      Result:=True;
      break;
     end;
   end;
finally
 Form1.Server.Contexts.UnlockList;
end;
end;


 
Сергей М. ©   (2009-10-29 22:12) [142]


>       except
>        Result:=False;
>       end;
>       Result:=True;


Сам-то понял, что ты тут творишь ?)


 
Dennis I. Komarov (htc)   (2009-10-29 22:29) [143]

а что? прогресс на лицо ;) и логика появилась...


 
Zalm ©   (2009-11-28 02:57) [144]

Как можно изнутри сервера вызвать эвент обработчика комманды как будто клиент прислал такую команду?


Procedure pr;
var
command : TidCommand;
begin
 command.CommandHandler.Command:="0x18";
 Form1.Client.CommandHandlers.Items[13].OnCommand(command);
end;


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


 
Zalm ©   (2009-12-01 13:16) [145]

Забанили тему что ли?...


 
Сергей М. ©   (2009-12-01 13:30) [146]

Да просто надаела уже эта тягомотина хуже горькой редьки)


 
Zalm ©   (2009-12-02 20:46) [147]

Ну давайте я новую создам?)
У меня больше нет вопросов кроме этого... может всё же ответите пожалуйста если знаете?)


 
Сергей М. ©   (2009-12-02 21:27) [148]


> давайте я новую создам?


Думаешь новая редька будет слаще ?)
Сомневаюсь)


> Как можно изнутри сервера вызвать эвент обработчика комманды


Как обычный метод обычного объекта.


 
Zalm ©   (2009-12-03 12:37) [149]

Вы смотрели мой пример? когда я так делаю ничего не происходит вобще


 
Сергей М. ©   (2009-12-03 12:46) [150]

Ну поставь брейкпойнт да посмотри что у тебя там не там или не так на самом деле происходит ..



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

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

Наверх





Память: 0.99 MB
Время: 0.009 c
2-1259779619
Danco
2009-12-02 21:46
2010.01.24
Смена запуска Unit


15-1258681417
Дмитрий С
2009-11-20 04:43
2010.01.24
Нужна программа для хранения секретной информации.


1-1234360353
vinixp
2009-02-11 16:52
2010.01.24
Картинка из веб страницы


2-1259566616
V@silij Iv@novich
2009-11-30 10:36
2010.01.24
Использование QReport


2-1259755341
Andjey
2009-12-02 15:02
2010.01.24
Получение хэндла потока





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский