Конференция "Сети" » Проблемма TIdTCPServer [D7, WinXP]
 
  • PonosetcDM © (17.06.10 15:50) [20]
    А как же быть с тем меньшинством???? Для которых эта "абсолютно нормальная логика" не одходит. Я не говорю, что мой проэкт не подходит под поняти "подавляющее большинство распределённых приложений", но просто интересно как быть...??
  • Сергей М. © (17.06.10 15:53) [21]
    Протокол инф.обмена должен соответствовать этой логике "меньшинства".
    Ну и, разумеется, реализация этого протокола должна быть соответствующей.
  • Anatoly Podgoretsky © (17.06.10 15:56) [22]
    > PonosetcDM  (17.06.2010 15:15:16)  [16]

    А ты сервер или спамер. Но ты имеешь право посылать сообщения
    подсоединившимся к тебе пользователям, если они готовы слушать тебя.
  • Anatoly Podgoretsky © (17.06.10 15:58) [23]
    > PonosetcDM  (17.06.2010 15:37:18)  [18]

    Постоянно опрашивать не надо, а надо ждать сообщения от сервера, как
    поступит так и обрабатывай. После установки соединения между сервером и
    клиентом нет разницы, они равноправны. Смотри методы и свойства TIdTCPServer
    и твоего клиента.
  • PonosetcDM © (17.06.10 16:24) [24]
    Anatoly Podgoretsky ©   (17.06.10 15:58) [23]
    Я не знаю прочитали  вы полностью нашу с Сергеем переписку или нет, пэтому уточню суть проблеммы:
    Есть приложение с TIdTCPServer(сервер) и приложение с TIdTCPClient(клиент).
    1. я делаю клиентом коннект к серверу   IdTCPClient1.Connect;
      все хорошо, все подлючается, все работает.
    2. я отправляю сообщение клиентом, серверу, он(сервер) обрабатывает его.
      все хорошо, все принято и обработано, все работает.
    3. я посылаю сообщение сервером, клиенту, он(клиент) обрабатывает его.
      все хорошо, все принято и обработано, все работает.

    Шаги 2 и 3 выполнять можно скока ХОШЬ....

    4. делаю клиентом дисконнект. все дисконнектится все нормально...
    5. делаю коннект, а вот тут "пффууук...." клиент грит, что он подконнектился, а сервер не реагирует, и ри попытке отправить сервером сообщение клиенту происходит "Connection Closed Grasfully"..., а при попытке повторного коннекта(без Disconnect), клиент говорит Already connected.. т.е. он считает, что он уже подключен...
  • Anatoly Podgoretsky © (17.06.10 16:30) [25]
    > PonosetcDM  (17.06.2010 16:24:24)  [24]

    Я как раз прочитал и ответил.
    После коннекта установлены двухсторонние отношения и клиент и сервер
    равноправны. Опрашивать ничего не надо, надо ждать сообщения в отдельном
    потоке конечно с использованием WaitForSingleObject
  • Сергей М. © (17.06.10 16:30) [26]

    > PonosetcDM ©   (17.06.10 16:24) [24]


    Ты так и не объяснил какая религия и почему запрещает тебе передавать данные клиенту непосредственнов в OnExecute
  • Anatoly Podgoretsky © (17.06.10 16:31) [27]
    > PonosetcDM  (17.06.2010 16:24:24)  [24]

    В ICS и это делать не надо, достаточно написать обработчик OnReceive, поток
    нужен для Инди. Но это моменты реализации.
  • PonosetcDM © (18.06.10 08:53) [28]
    Воооо.... ваще чума....
    я запустил программу(сервер)
    подключился к ней по telnet из cmd,
    сервак послал клиенту сообщение, все окей,
    принято telnet'ом, обработано...
    закрываю telnet,
    открываю telnet,
    делаю коннект "типа все окей", сервак шлет сообщение клиенту и.......
     правильно  "Connection Closed Grasfully"... ваще жуть...
  • Сергей М. © (18.06.10 09:28) [29]

    > ваще чума


    > ваще жуть


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

    Ведь не ты один этим списком пользуешься - им еще и TIdCustomTCPServer пользуется, причем в 1-ю очередь !

    При обработке событий коннекта/дисконнекта IdCustomTCPServer обращается к этому списку, выполняя попытку заблокировать его для внесения соотв.изменения, например, для удаления Item[0] после дисконнекта 1-го клиента и вновь создания Item[0] при коннекте ..

    А ты взял и уселся на него верхом, не пуская никого покататься)

    Вот тебе и грабли)
  • Slym © (18.06.10 10:02) [30]
    1. протокол - говно
    ты где видал что сначала идет список длинн, потом список данных
    (табличное представление не в счет)
    общепринято: длинна-значание, длинна-значение

    2. описание структур - говно, дублирующие поля totalSize и ParamsLength в итоге потенциальное переполнение буфера когда totalSize<>Sum(ParamsLength)

    3. работа с памятью - говно (cp := 2 + SizeOf(cardinal) + tmsg.fHeader.ParamCount * Sizeof(cardinal);)

    4. работа с потоками - говно, общение с VCL в потоке (Memo1.Lines.Add)

    это только про сервер...
    про клиента:
    таймер убил меня, читать дальше нет мочи
  • Slym © (18.06.10 10:30) [31]
    вот сравни с [3]
    procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
    var
     tmsg : TPackage;
     i: byte;
     recvfs: TFileStream;
     MemoLines:string;
    begin
     with AContext.Connection.Socket,tmsg.fHeader,tmsg.fData do
     begin
       //начинаем жуткое месиво текстовых (ReadLn) и бинарных (ReadByte) операций
       totalSize :=StrToInt64(ReadLn);//нигде не использую т.к. нафиг надо...
       cmd:=ReadByte;
       ParamCount := ReadByte;

       SetLength(ParamsLength,ParamCount);
       for i:=0 to ParamCount-1 do
         ParamsLength[i]:=ReadLongInt(false);

       SetLength(Params,ParamCount);
       for i:=0 to ParamCount-1 do
         Params[i]:=ReadString(ParamsLength[i],enDefault);

       MemoLines:='';
       MemoLines:=MemoLines+'*********** We have a new message*******'+#13#10;
       MemoLines:=MemoLines+'   Message CMD Code = '+ IntToStr(tmsg.fHeader.cmd)+#13#10;
       MemoLines:=MemoLines+'   Message Params: '+#13#10;
       for i:=0 to ParamCount-1 do
         MemoLines:=MemoLines+'      ' + (Params[i])+#13#10;

       Case cmd of
         1 :  MemoLines:=MemoLines+'We have a new connection...'+#13#10;
         2 :  MemoLines:=MemoLines+'This is a message'+#13#10;
         3 :  begin
                recvfs:= TFileStream.Create(ExtractFileName(Params[0])+'.tmp',fmCreate);
                try
                   ReadStream(recvfs,StrToInt(Params[1]),false);
                finally
                   recvfs.Free;
                end;
                   MemoLines:=MemoLines+'-----> New File upload complete...'+#13#10;
              end;
       end;
     end;
     MemoLines:=MemoLines+'*********** End of new message*******'+#13#10;

     //ПОТОКОБЕЗОПАСНО_ПЕРЕДАЕМ(MemoLines,в Memo1.Lines);
    end;

  • Anatoly Podgoretsky © (18.06.10 10:31) [32]

    > делаю коннект "типа все окей", сервак шлет сообщение клиенту
    > и.......
    >  правильно  "Connection Closed Grasfully"... ваще жуть..
    > .

    Претензии к реализации сервера, невероятно кривая.
  • Сергей М. © (18.06.10 10:34) [33]

    > Anatoly Podgoretsky ©   (18.06.10 10:31) [32]


    Какая бы ни была кривая, но UnlockList-то надо вызывать)
  • Slym © (18.06.10 10:54) [34]
    procedure TForm1.SendPackage(pcmd, pparamCount: byte;
    pparams: array of string);
    var
     tmsg:TPackage;
     buf:TMemoryStream;
     List:TList;
     i:integer;
    begin
     buf:=TMemoryStream.Create;
     try
       //формирование TPackage можно нафик выкинуть
       with tmsg.fHeader,tmsg.fData do
       begin
         cmd:= pcmd;
         ParamCount := pparamCount;
         SetLength(ParamsLength,ParamCount);
         SetLength(Params,ParamCount);
         for i:=0 to ParamCount-1 do
         begin
           Params[i]:=pparams[i];
           ParamsLength[i]:=length(Params[i]);
         end;

         buf.WriteBuffer(cmd,SizeOf(cmd));
         buf.WriteBuffer(ParamCount,SizeOf(ParamCount));
         for i:=0 to ParamCount-1 do
           buf.WriteBuffer(ParamsLength[i],SizeOf(cardinal));
         for i:=0 to ParamCount-1 do
           buf.WriteBuffer(PChar(Params[i])^,ParamsLength[i]);
       end;

       //шо за нах!Items[0]! пошлем всех!
       List:=IdTCPServer1.Contexts.LockList;
       try
         for i:=0 to List.Count-1 do
         with TIdContext(List.Items[i]).Connection.Socket do
         begin
           WriteLn(IntToStr(buf.Size));
           Write(buf);
         end;
       finally
         IdTCPServer1.Contexts.UnlockList;//ОБЯЗАТЕЛЬНО!!!
       end;
     finally
       buf.Free;//ОБЯЗАТЕЛЬНО!!!
     end;
    end;

  • Slym © (18.06.10 11:16) [35]
    ЗАБЫЛ добавить:
    как только выходим из IdTCPServer1Execute - финиталякомедия конекшен рвется, так что переделывай в все в одном IdTCPServer1Execute или как то усыпляй IdTCPServer1Execute...
  • Anatoly Podgoretsky © (18.06.10 11:18) [36]
    > Сергей М.  (18.06.2010 10:34:33)  [33]

    Это часть кривизны.
  • PonosetcDM © (18.06.10 11:48) [37]
    Блин я согласен все замечания хороши, базара ноль... да вот проблемма остается актуальной..
    на форме компоненты TIdTCPServer, TMemo и ТБатон
    вот код куда уж проще то...

    unit Unit1;

    interface

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

    type
     TForm1 = class(TForm)
       IdTCPServer1: TIdTCPServer;
       Memo1: TMemo;
       BitBtn1: TBitBtn;
       procedure IdTCPServer1Execute(AContext: TIdContext);
       procedure FormCreate(Sender: TObject);
       procedure FormDestroy(Sender: TObject);
       procedure BitBtn1Click(Sender: TObject);
       procedure IdTCPServer1Connect(AContext: TIdContext);
       procedure IdTCPServer1Disconnect(AContext: TIdContext);
     private
       { Private declarations }
     public
       { Public declarations }
     end;

    var
     Form1: TForm1;

    implementation

    {$R *.dfm}

    procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
    var s:string;
    begin
     s:=AContext.Connection.IOHandler.ReadLn;
     Memo1.Lines.Add(s);
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
     IdTCPServer1.Active:=true;
    end;

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

    procedure TForm1.BitBtn1Click(Sender: TObject);
    var i:integer;
    begin
      try
        for i:=0 to IdTCPServer1.Contexts.LockList.Count-1 do
        with TIdContext(IdTCPServer1.Contexts.LockList.Items[i]).Connection.Socket do
          WriteLn('123');
      finally
        IdTCPServer1.Contexts.UnlockList;
      end;
    end;

    procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
    begin
     Memo1.Lines.Add('we have a new connection')
    end;

    procedure TForm1.IdTCPServer1Disconnect(AContext: TIdContext);
    begin
     Memo1.Lines.Add('Client disconnected');
    end;

    end.

    иииииииии............ все теже грабли...

    Запускаю эту прогу,
    запускаю телнет
    коннект телнета "o localhost 12312"
    нажимаю на батон, в окне телнета появляется "123",
    нажимаю на батон ищё раз, в окне телнета появляется ищё "123",
    закрываю телнет, срабатывает дисконнект
    запускаю телнет опять, прога при этом не перезапускалась(естественно)...
    делаю телнетом "o localhost 12312", и даже коннект у сервера не срабатывает....
    все по шагам разжевал....
  • Сергей М. © (18.06.10 11:57) [38]

    > все теже грабли


    Ну где-же "теже" ?
    Connection closed gracefully как рукой сняло)

    И, кстати, ты в [35] вник ?
  • PonosetcDM © (18.06.10 12:04) [39]
    Нууу не знаю что у Вас сняло, у мя как было так и осталось, какая у Вас версия Indy????

    Про [35] хзхз, почиму это коннекшен рвется????

    и что за усыпляй???

    у мя когда клиент коннект сделал, заходит в и
    IdTCPServer1Execute(AContext: TIdContext);
    останавливается на AContext.Connection.IOHandler.ReadLn,
    пока не придет что-ть.
 
Конференция "Сети" » Проблемма TIdTCPServer [D7, WinXP]
Есть новые Нет новых   [118586   +38][b:0][p:0.003]