Indy запись пропускает одну команду

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Indy запись пропускает одну команду

Сообщение Sharfik » 16.11.2019 08:16:45

Преветствую.
В чем ошибаюсь? Ниже код передачи файла. Клиент отправляет команду, сервер подтверждает что можно передавать. Клиент записывает место куда сохранить файл и передает сам файл.
Сервер принимает файл и отправляет подтверждение что принял. Но клиент упорно не принимает подтверждение. Методом "дурака" поставил две записи подряд. В итоге ответ "FILEOK1" не приходит, а "FILEOK2" приходит.
:?
Клиент:
Код: Выделить всё
         IdCmdTCPClient1.ReadTimeout:=7000;
         iCmdResult:=403;
         iCmdResult:=IdCmdTCPClient1.SendCmd(sCmd,-1,cmdEncoding);
         if iCmdResult=101 then
         begin
            IdCmdTCPClient1.IOHandler.WriteLn(sServerFilePath,cmdEncoding);
            mClientLog.Lines.Add('101; Начинаю передачу файла');
            try
              FileStream := TFileStream.Create(sFilePath, fmOpenRead or fmShareDenyWrite);
              iSize      := FileStream.Size;
              IdCmdTCPClient1.IOHandler.LargeStream := True;
              IdCmdTCPClient1.IOHandler.WriteBufferOpen;
              IdCmdTCPClient1.IOHandler.Write(iSize);
              IdCmdTCPClient1.IOHandler.Write(FileStream, iSize);
              IdCmdTCPClient1.IOHandler.WriteBufferClose;
              sCmdResult:='0';
              try                 
                sCmdResult:=IdCmdTCPClient1.IOHandler.ReadLn();               
              except
              end;

              if StrToInt(sCmdResult)=StrToInt('200') then
              begin
                 mClientLog.Lines.Add(Format('200; Файл отправлен. Передано %d байт',[iSize]));
              end
              else begin
                 mClientLog.Lines.Add('507; Ошибка отправки файла');
              end;

              FileStream.Free;
            except
              FileStream.Free;
              mClientLog.Lines.Add('500; Ошибка получения файла');
            end;
         end
         else begin
            mClientLog.Lines.Add(Format('%d; Нет разрешения на передачу файлов',[iCmdResult]));
         end;


Сервер:
Код: Выделить всё
if NetDirectoryCreate(ExtractFilePath(sFilePath)) then
                   begin
                       sFilePath:=UTF8ToSys(sFilePath);
                       FileStream:=TMemoryStream.Create;
                       FileStream.Position:=0;
                       try
                          ASender.Context.Connection.IOHandler.LargeStream:=True;
                          iSize:=ASender.Context.Connection.IOHandler.ReadInt64();
                          ASender.Context.Connection.IOHandler.ReadStream(FileStream,iSize);
                          if FileStream.Size=iSize then
                             FileStream.SaveToFile(sFilePath);
                          FileStream.Free;
                          iCmdResult:=MRNSERVERREPLY_GREETING;
                          ThreadSafeLogAdd(format('%d; %s; File saved',[iCmdResult,tmpClientItem.Login]));
                       except
                          FileStream.Free;
                          SysUtils.DeleteFile(sFilePath);
                          iCmdResult:=MRNSERVERREPLY_ERROR;
                          ThreadSafeLogAdd(format('%d; %s; Error save file',[iCmdResult,tmpClientItem.Login]));
                       end;

                       if iCmdResult=MRNSERVERREPLY_GREETING then
                       begin
                         ASender.Context.Connection.IOHandler.WriteLn('FILEOK1');
                         ASender.Context.Connection.IOHandler.WriteLn('FILEOK2');
                       end;

                       //Запись атрибутов файлов
 
                   end
                   else begin
                      ThreadSafeLogAdd(format('%d; %s; Error get directory path',[iCmdResult,tmpClientItem.Login]));
                   end;
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 760
Зарегистрирован: 20.07.2013 01:04:30

Re: Indy запись пропускает одну команду

Сообщение Снег Север » 16.11.2019 15:41:59

Sharfik, а если на синапс переделать? Я последнее время и на делфи избегаю пользоваться Инди.
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 2993
Зарегистрирован: 27.11.2007 16:14:47

Re: Indy запись пропускает одну команду

Сообщение Sharfik » 16.11.2019 18:22:01

Снег Север писал(а):Sharfik, а если на синапс переделать? Я последнее время и на делфи избегаю пользоваться Инди.

Мне хоть бы на чем, я пока начал разбираться только, кода не много. Нужно чтобы одну проблему на работе решить и забыть. Просто мне показалось что по Indy больше документации и примеров.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 760
Зарегистрирован: 20.07.2013 01:04:30

Re: Indy запись пропускает одну команду

Сообщение olegy123 » 17.11.2019 06:57:22

Снег Север писал(а):Sharfik, а если на синапс переделать? Я последнее время и на делфи избегаю пользоваться Инди.
просто не умеете готовит.

Добавлено спустя 19 минут 51 секунду:
Sharfik писал(а):IdCmdTCPClient1.IOHandler.WriteBufferClose;
меня смущает это..
IOHandler - это низкоуровневые операции с сокетом, при этом ведется работа с высоким уровнем IdCmdTCPClient1,
как себя ведет IdCmdTCPClient1 после операций с IOHandler.. WriteBufferClose? правильно ли это? может IdCmdTCPClient1 глохнет на команду..
Тем более cmd подразумевает работу только с текстом. переключать IOHandler на бинарные данные - это Hack.
Это нужно знать тонкости работы сокета, обвязки и протоколов высокого уровня..


Лично я все реализовал на одном уровне IdTCPServer/IdTCPClient с Write/WriteBuffer и т.п.
Все бы свел в один протокол.
Код: Выделить всё
Клиент -> Привет#10#13
Сервер -> Привет#10#13
Клиент -> Файл#10#13
Клиент -> 1024#10#13
Клиент -> (файл)
Сервер -> принял 1024#10#13
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: Indy запись пропускает одну команду

Сообщение Sharfik » 17.11.2019 16:11:39

olegy123 писал(а):IOHandler - это низкоуровневые операции с сокетом, при этом ведется работа с высоким уровнем IdCmdTCPClient1,
как себя ведет IdCmdTCPClient1 после операций с IOHandler.. WriteBufferClose? правильно ли это? может IdCmdTCPClient1 глохнет на команду..
Тем более cmd подразумевает работу только с текстом. переключать IOHandler на бинарные данные - это Hack.
Это нужно знать тонкости работы сокета, обвязки и протоколов высокого уровня..

Писалось на основе документации что нашел и примеров их же. И буфера записи и буфер чтения это разное. Мне же после записи надо прочитать, а сервер прочитав первую команду записи игнорит.

просто не умеете готовит.

тут согласен, чаще всего виноват не компилятор, а программист.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 760
Зарегистрирован: 20.07.2013 01:04:30

Re: Indy запись пропускает одну команду

Сообщение olegy123 » 18.11.2019 12:31:36

Я про то что можно свести к простому
Код: Выделить всё
IdTCPClient.WriteLn('Hello');     
                                                 cmd:=Connection.ReadLn() ;
                                                 if cmd='Hello' then
                                                          Connection.writeln('Сервер №1');
res:=IdTCPClient.ReadLn();
IdTCPClient.WriteLn('file');     
FileSize:=file.size();// var filesize:integer;
IdTCPClient.WriteBuffer(filesize,sizeof(integer));     
IdTCPClient.writeLong(file.data,filesize);     

                                                 if cmd='file' then
                                                 begin
                                                          Connection.ReadBuffer(filesize,sizeof(integer));
                                                          Connection.ReadBuffer(file,filesize);
                                                          Connection.WriteLn('ok');
                                                 end
res:=IdTCPClient.ReadLn();// ok

Я пишу по памяти, но можно все свести на уровне TCP компонент.
Именно так устроены протоколы высокого уровня.

Добавлено спустя 5 минут 9 секунд:
могут быть проблемы с Java/Android или другими системами, так как при пересылке raw битовых значений Integer/Long/Float
может сущестовать обратная битность, Big-Endian/little-Endian
тогда нужно распознать системы и нормализовать данные, либо переводит все в String значение..
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: Indy запись пропускает одну команду

Сообщение Sharfik » 19.11.2019 00:30:48

Насколько я понял, в компоненте Indy, который командами работает, так и есть. Просто обработчик и парсер добавлен готовый.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 760
Зарегистрирован: 20.07.2013 01:04:30

Re: Indy запись пропускает одну команду

Сообщение Sharfik » 25.11.2019 00:53:21

Где найти хоть какую то документацию по Synapse клиент-серсер tcp ?
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 760
Зарегистрирован: 20.07.2013 01:04:30

Re: Indy запись пропускает одну команду

Сообщение Снег Север » 25.11.2019 10:50:05

Sharfik писал(а):Где найти хоть какую то документацию по Synapse клиент-серсер tcp ?

Сомневаюсь, что существует такая документация. А примеров в интернете - пруд пруди...
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 2993
Зарегистрирован: 27.11.2007 16:14:47

Re: Indy запись пропускает одну команду

Сообщение iskander » 25.11.2019 11:03:56

Когда-то попадалась на просторах ни больше ни меньше "Книга о Synapse".
iskander
энтузиаст
 
Сообщения: 590
Зарегистрирован: 08.01.2012 18:43:34

Re: Indy запись пропускает одну команду

Сообщение Снег Север » 25.11.2019 11:15:33

iskander писал(а):Когда-то попадалась на просторах ни больше ни меньше "Книга о Synapse".

Не отсюда ли?
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 2993
Зарегистрирован: 27.11.2007 16:14:47

Re: Indy запись пропускает одну команду

Сообщение iskander » 25.11.2019 11:20:42

Похоже она самая.
iskander
энтузиаст
 
Сообщения: 590
Зарегистрирован: 08.01.2012 18:43:34

Re: Indy запись пропускает одну команду

Сообщение olegy123 » 25.11.2019 14:30:17

Sharfik писал(а):Насколько я понял, в компоненте Indy, который командами работает, так и есть.
так и есть.

Я вообще на Инди делал чат с возможностью обмена файлами, в планах было использование звука.
Там ничего сложного нет.
Synapse нужно садить на TThread - что потом опять же превращает его в Indy.

Там и там нужно выдумывать протокол.
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20


Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 5

Рейтинг@Mail.ru