• 0
CodeWriter

System.Net.Socket.TSocket

Вопросы

Приветствую всех. 
Использую компонент 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?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 ответа на этот вопрос

  • 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

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

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

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

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