Перейти к содержанию
Fire Monkey от А до Я
  • 0

System.Net.Socket.TSocket


CodeWriter

Вопрос

Приветствую всех. 
Использую компонент System.Net.Socket.TSocket для отправки/получения данных по TCP в потоке. Код взял из этой темы: http://fire-monkey.ru/topic/2834-электросчетчики-меркурий-отправка-получение-данных-с-ip-адреса/?page=2#comment-17082
Подлючение с помощью Connect и отправка данных через Send происходит без проблем. Но функция Receive никак не реагирует на получение ответа, хотя WireShark показывает, что данные приходят. 
Пытался разными способами получить положительный результат, вплоть до использования асинхронных методов BeginReceive/EndReceive. 
Файервол, антивир отключал, порты открывал... но безрезультатно и для Windows и для Android.
Кто пользовался этим компонентом подскажите как правильно получать ответ с помощью Receive?

Ссылка на комментарий

Рекомендуемые сообщения

  • 0

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

Процедура SendCommand(Var ASendingData : TSendingData), в блокирующем режиме посылает текст на сервер и получает результат.

unit UnitExcavatorWinTCPThread;

interface

uses
  classes,
  SysUtils,
  System.Types,
  System.Generics.Collections,
  System.Win.ScktComp,
  UnitExcavatorThread,
  UnitExcavatorTypes;

  type
    TExcavatorWinTCPThread = class(TExcavatorThread)
    protected
      FClientSocket : TClientSocket;

      CStream : TWinSocketStream;
      procedure CreateNetwork; override;
      procedure DestroyNetwork; override;
      procedure SendCommand(Var ASendingData : TSendingData); override;
    public
    end;

  implementation

procedure TExcavatorWinTCPThread.CreateNetwork;
begin
  FClientSocket:=TClientSocket.Create(Nil);
  FClientSocket.Host:=FExcavatorInstance.Host;
  FClientSocket.Port:=FExcavatorInstance.PortTCP;
  FClientSocket.ClientType:=TClientType.ctBlocking;

  CStream:=TWinSocketStream.Create(FClientSocket.Socket, FTimeouts.ConnectTimeout);
end;

procedure TExcavatorWinTCPThread.DestroyNetwork;
begin
  if Assigned(CStream) then
    FreeAndNil(CStream);
  if Assigned(FClientSocket) then
    FreeAndNil(FClientSocket);
end;

procedure TExcavatorWinTCPThread.SendCommand(Var ASendingData : TSendingData);
Var AReaded, ACount : integer;
    ABuffer : TBytes;
    ACommand, AStringBuffer : AnsiString;
    ACommandIdString : String;
    ADone : Boolean;
begin
  ACommandIdString:='"id":' + ASendingData.CommandId.ToString;
  ASendingData.Error:=False;
  ACommand:=AnsiString(ASendingData.Value) + #10;
  ASendingData.Value:='';
  if Not FClientSocket.Active then
    try
      FClientSocket.Open;
    except
      on E:Exception do
      begin
        ASendingData.Error:=True;
        ASendingData.Value:=E.Message;
        exit;
      end;
    end;
  if FClientSocket.Active then
  begin
    try
      // Считываем из буфера все что там есть.
      while CStream.WaitForData(CStream.TimeOut) do
        AStringBuffer:=FClientSocket.Socket.ReceiveText;
    except
    end;
    try
      FClientSocket.Socket.SendText(ACommand);
    except
      on E:Exception do
      begin
        ASendingData.Error:=True;
        ASendingData.Value:=E.Message;
        exit;
      end;
    end;
    try
      ADone:=False;
      ACount:=0;
      repeat
        if CStream.WaitForData(CStream.TimeOut) then
          ASendingData.Value:=ASendingData.Value + FClientSocket.Socket.ReceiveText;
        if ASendingData.Value.Contains('"id":1') then
          break;
        if ASendingData.Value.Contains(ACommandIdString) then
          break;
        Inc(ACount);
        if ACount > 2 then
          break;
      until ADone;
    except
      on E:Exception do
      begin
        ASendingData.Error:=True;
        ASendingData.Value:=E.Message;
        exit;
      end;
    end;
  end
  else
  begin
    ASendingData.Error:=True;
    ASendingData.Value:='Not connected';
  end;
end;

end.

 

Ссылка на комментарий
  • 0
4 часа назад, Евгений Корепов сказал:

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

Процедура SendCommand(Var ASendingData : TSendingData), в блокирующем режиме посылает текст на сервер и получает результат.

Спойлер


unit UnitExcavatorWinTCPThread;

interface

uses
  classes,
  SysUtils,
  System.Types,
  System.Generics.Collections,
  System.Win.ScktComp,
  UnitExcavatorThread,
  UnitExcavatorTypes;

  type
    TExcavatorWinTCPThread = class(TExcavatorThread)
    protected
      FClientSocket : TClientSocket;

      CStream : TWinSocketStream;
      procedure CreateNetwork; override;
      procedure DestroyNetwork; override;
      procedure SendCommand(Var ASendingData : TSendingData); override;
    public
    end;

  implementation

procedure TExcavatorWinTCPThread.CreateNetwork;
begin
  FClientSocket:=TClientSocket.Create(Nil);
  FClientSocket.Host:=FExcavatorInstance.Host;
  FClientSocket.Port:=FExcavatorInstance.PortTCP;
  FClientSocket.ClientType:=TClientType.ctBlocking;

  CStream:=TWinSocketStream.Create(FClientSocket.Socket, FTimeouts.ConnectTimeout);
end;

procedure TExcavatorWinTCPThread.DestroyNetwork;
begin
  if Assigned(CStream) then
    FreeAndNil(CStream);
  if Assigned(FClientSocket) then
    FreeAndNil(FClientSocket);
end;

procedure TExcavatorWinTCPThread.SendCommand(Var ASendingData : TSendingData);
Var AReaded, ACount : integer;
    ABuffer : TBytes;
    ACommand, AStringBuffer : AnsiString;
    ACommandIdString : String;
    ADone : Boolean;
begin
  ACommandIdString:='"id":' + ASendingData.CommandId.ToString;
  ASendingData.Error:=False;
  ACommand:=AnsiString(ASendingData.Value) + #10;
  ASendingData.Value:='';
  if Not FClientSocket.Active then
    try
      FClientSocket.Open;
    except
      on E:Exception do
      begin
        ASendingData.Error:=True;
        ASendingData.Value:=E.Message;
        exit;
      end;
    end;
  if FClientSocket.Active then
  begin
    try
      // Считываем из буфера все что там есть.
      while CStream.WaitForData(CStream.TimeOut) do
        AStringBuffer:=FClientSocket.Socket.ReceiveText;
    except
    end;
    try
      FClientSocket.Socket.SendText(ACommand);
    except
      on E:Exception do
      begin
        ASendingData.Error:=True;
        ASendingData.Value:=E.Message;
        exit;
      end;
    end;
    try
      ADone:=False;
      ACount:=0;
      repeat
        if CStream.WaitForData(CStream.TimeOut) then
          ASendingData.Value:=ASendingData.Value + FClientSocket.Socket.ReceiveText;
        if ASendingData.Value.Contains('"id":1') then
          break;
        if ASendingData.Value.Contains(ACommandIdString) then
          break;
        Inc(ACount);
        if ACount > 2 then
          break;
      until ADone;
    except
      on E:Exception do
      begin
        ASendingData.Error:=True;
        ASendingData.Value:=E.Message;
        exit;
      end;
    end;
  end
  else
  begin
    ASendingData.Error:=True;
    ASendingData.Value:='Not connected';
  end;
end;

end.

 

 

Благодарю за код, для windows может пригодиться. Но нужен код с использованием кроссплатформенных компонентов. Для Android компонент System.Win.ScktComp.TClientSocket не подходит.

System.Net.Socket.TSocket работает и отправляет, всё как положено. Но ума не приложу, почему принять ответ, который приходит (WireShark тому свидетель) не получается?

Изменено пользователем CodeWriter
Ссылка на комментарий
  • 0
5 часов назад, CodeWriter сказал:

Благодарю за код, для windows может пригодиться. Но нужен код с использованием кроссплатформенных компонентов. Для Android компонент System.Win.ScktComp.TClientSocket не подходит.

System.Net.Socket.TSocket работает и отправляет, всё как положено. Но ума не приложу, почему принять ответ, который приходит (WireShark тому свидетель) не получается?

Сейчас только увидел в тексте " и для Android", сорри. 

Вы кусок кода отправки/получения покажите, может кто увидит в чем проблема.

Ссылка на комментарий
  • 0

Используйте TCPServer/TCPClient Для отправки по TCP.  Там принцип работы тот же, многие методы/свойства идентичны. У меня все работает на всех платформах

Прием данных в TCPServer делайте в OnExecute. В TCPClient для приема используйте поток:

procedure TTCPConnectThread.Execute;
begin
    while not Terminated do begin
        try
            if TCPClient.Connected then begin
               //Здесь считываем данные, например с помощью TCPClient.IOHandler.ReadLn, и обрабатываем их
            end;
        finally
            sleep(100);
        end;
    end;
end;
        

 

Изменено пользователем Alex7wrt
Ссылка на комментарий

Присоединяйтесь к обсуждению

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

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...