Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Работа с сетью в Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 31.03.2017, 01:35   #1
Fox78
Пользователь
 
Регистрация: 17.03.2017
Сообщений: 28
По умолчанию TCP IP Терминал

Здравствуйте, задача такова:
Есть устройство, которое по tcp кидает данные.
Его адрес и порт известны.
Мне необходимо получать эти данные для дальнейшей обработки.
Я искал на форумах информацию по компоненту Indy.
Пишут вроде бы все просто: подключился, считал, отключился.
Но беда в том, что предлагают использовать функцию ReadLn, а компилятор на нее ругается.

Вот кусок кода:

procedure TForm1.Cnct_client_btnClick(Sender: TObject);
begin
IdTCPClient1.Host:='192.168.1.45'; // IP-устройства
IdTCPClient1.Port:=23;
IdTCPClient1.Connect;
end;

procedure TForm1.Dcnct_client_btnClick(Sender : TObject);
begin
IdTCPClient1.Disconnect;
end;

procedure TForm1.Client_RDLn_btnClick(Sender: TObject);
var
str: string;
begin
str:=IdTCPClient1.ReadLn; // здесь ругается
end;

Помогите, пожалуйста разобраться.
Fox78 вне форума Ответить с цитированием
Старый 31.03.2017, 05:57   #2
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Как ругается? Что пишет?
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .
Pavia вне форума Ответить с цитированием
Старый 31.03.2017, 06:56   #3
Fox78
Пользователь
 
Регистрация: 17.03.2017
Сообщений: 28
По умолчанию

Цитата:
Сообщение от Pavia Посмотреть сообщение
Как ругается? Что пишет?
[dcc32 Error] DataMan.pas(46): E2003 Undeclared identifier: 'ReadLn'

Может имеет значение... стоит Delphi 10.1 Berlin

Возможно нужно использовать IdTCPClient1.Socket.ReadLn?

Программа компилируется, но при нажатии кнопки чтения данных программа виснет.

procedure TForm1.Cnct_client_btnClick(Sender: TObject);
begin
IdTCPClient1.Host:='192.168.1.45'; // IP-устройства
IdTCPClient1.Port:=23;
IdTCPClient1.Connect;
end;

procedure TForm1.Dcnct_client_btnClick(Sender : TObject);
begin
IdTCPClient1.Disconnect;
end;

procedure TForm1.Client_RDLn_btnClick(Sender: TObject);
begin
Memo1.Lines.Append(IdTCPClient1.Soc ket.ReadLn);
end;

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

Последний раз редактировалось Fox78; 31.03.2017 в 07:48.
Fox78 вне форума Ответить с цитированием
Старый 31.03.2017, 07:44   #4
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

У вас ReadLn не в той процедуре procedure TForm1.Client_RDLn_btnClick(Sender: TObject);

нужно насколько я помню здесь ответ ловить
Код:
procedure TForm1.IdTCPClient1Work(Sender: TObject; AWorkMode: TWorkMode;
  const AWorkCount: Integer);
var
str: string;
begin
if AWorkMode = wmRead then
str:=IdTCPClient1.ReadLn;
end;
Ну или в потоке можно сделать

Последний раз редактировалось Aliens_wolfs; 31.03.2017 в 11:12.
Aliens_wolfs вне форума Ответить с цитированием
Старый 31.03.2017, 08:42   #5
Fox78
Пользователь
 
Регистрация: 17.03.2017
Сообщений: 28
По умолчанию

Цитата:
Сообщение от Aliens_wolfs Посмотреть сообщение
У вас ReadLn не в той процедуре procedure TForm1.Client_RDLn_btnClick(Sender: TObject);

нужно насколько я помню здесь ответ ловить
Код:
procedure TForm1.IdTCPClient1Work(Sender: TObject; AWorkMode: TWorkMode;
  const AWorkCount: Integer);
var
str: string;
begin
if AWorkMode = wmRead then
str:=IdTCPClient1.ReadLn;
end;
Ну или в потоке
str:=IdTCPClient1.ReadLn; - компилятор не понимает эту строку, ругается на ReadLn.
Если же использую IdTCPClient1.Socket.ReadLn, то подвешивается программа. Нажимаю на кнопку закрытия соединения(IdTCPClient1.Disconnect; ), IdTCPClient1.Connected возвращает True.
Fox78 вне форума Ответить с цитированием
Старый 31.03.2017, 09:52   #6
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

Я на D7 делал, сейчас на XE посмотрю, там есть небольшое отличие IdTCPClient1.Socket.ReadLn и IdTCPClient1.ReadLn


Вот накидал код в потоке проверь

Код:
type
  TForm1 = class(TForm)
    Button1: TButton;
    IdTCPClient1: TIdTCPClient;
    Memo1: TMemo;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

    type
  TMyClientThread = class(TThread)
  private
   FIdTCPClient: TIdTCPClient;
    FStrRecieve: string;
  Protected
   procedure Execute; Override;
   procedure Recieve; virtual;
  public
    constructor Create(Ip: string; Port: Integer); virtual;
   destructor Destroy; override;
   procedure Stoped; virtual;
   procedure OnStop; virtual;
end;

var
  Form1: TForm1;
MyClientThread: TMyClientThread=nil;


implementation

{$R *.dfm}

constructor TMyClientThread.Create(Ip: string; Port: Integer);
begin
  inherited Create(false);
  FreeOnTerminate := True;
  FIdTCPClient:= TIdTCPClient.Create(nil);
  FIdTCPClient.Host:= Ip;
  FIdTCPClient.Port:= Port;
end;


destructor TMyClientThread.Destroy;
begin
  Synchronize(OnStop);
  FreeAndNil(FIdTCPClient);
  MyClientThread:= nil;
  inherited;
end;

procedure TMyClientThread.OnStop;
begin
Form1.Memo1.Lines.Add('Stop ' + FIdTCPClient.Host);
end;

procedure TMyClientThread.Recieve;
begin
Form1.Memo1.Lines.Add(FStrRecieve);
end;

procedure TMyClientThread.Stoped;
begin
Terminate;
 FIdTCPClient.Socket.Binding.CloseSocket;
end;

procedure TMyClientThread.Execute;
begin
  FIdTCPClient.Connect;
//Проверяем наше соединение
if not FIdTCPClient.Socket.Connected then
exit;
//Если соединение есть то ждем данные
while not Terminated do
begin
  FStrRecieve:= FIdTCPClient.Socket.ReadLn;
  if FStrRecieve <> '' then
  Synchronize(Recieve);
end;

end;

//Подключаемся
procedure TForm1.Button1Click(Sender: TObject);
begin
if not Assigned(MyClientThreadthen
MyClientThread:= TMyClientThread.Create('192.168.1.45', 23);
end;

//Отключаемся
procedure TForm1.Button2Click(Sender: TObject);
begin
if Assigned(MyClientThread) then
MyClientThread.Stoped;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Button2Click(nil);
end;

end.

Последний раз редактировалось Aliens_wolfs; 31.03.2017 в 14:27.
Aliens_wolfs вне форума Ответить с цитированием
Старый 31.03.2017, 11:12   #7
Fox78
Пользователь
 
Регистрация: 17.03.2017
Сообщений: 28
По умолчанию

Спасибо! До компьютера доберусь и сразу проверю!
Fox78 вне форума Ответить с цитированием
Старый 01.04.2017, 04:19   #8
Fox78
Пользователь
 
Регистрация: 17.03.2017
Сообщений: 28
По умолчанию

Цитата:
Сообщение от Aliens_wolfs Посмотреть сообщение
Я на D7 делал, сейчас на XE посмотрю, там есть небольшое отличие IdTCPClient1.Socket.ReadLn и IdTCPClient1.ReadLn


Вот накидал код в потоке проверь

Код:
type
  TForm1 = class(TForm)
    Button1: TButton;
    IdTCPClient1: TIdTCPClient;
    Memo1: TMemo;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

    type
  TMyClientThread = class(TThread)
  private
   FIdTCPClient: TIdTCPClient;
    FStrRecieve: string;
  Protected
   procedure Execute; Override;
   procedure Recieve; virtual;
  public
    constructor Create(Ip: string; Port: Integer); virtual;
   destructor Destroy; override;
   procedure Stoped; virtual;
   procedure OnStop; virtual;
end;

var
  Form1: TForm1;
MyClientThread: TMyClientThread=nil;


implementation

{$R *.dfm}

constructor TMyClientThread.Create(Ip: string; Port: Integer);
begin
  inherited Create(false);
  FreeOnTerminate := True;
  FIdTCPClient:= TIdTCPClient.Create(nil);
  FIdTCPClient.Host:= Ip;
  FIdTCPClient.Port:= Port;
end;


destructor TMyClientThread.Destroy;
begin
  Synchronize(OnStop);
  FreeAndNil(FIdTCPClient);
  MyClientThread:= nil;
  inherited;
end;

procedure TMyClientThread.OnStop;
begin
Form1.Memo1.Lines.Add('Stop ' + FIdTCPClient.Host);
end;

procedure TMyClientThread.Recieve;
begin
Form1.Memo1.Lines.Add(FStrRecieve);
end;

procedure TMyClientThread.Stoped;
begin
Terminate;
 FIdTCPClient.Socket.Binding.CloseSocket;
end;

procedure TMyClientThread.Execute;
begin
  FIdTCPClient.Connect;
//Проверяем наше соединение
if not FIdTCPClient.Socket.Connected then
exit;
//Если соединение есть то ждем данные
while not Terminated do
begin
  FStrRecieve:= FIdTCPClient.Socket.ReadLn;
  if FStrRecieve <> '' then
  Synchronize(Recieve);
end;

end;

//Подключаемся
procedure TForm1.Button1Click(Sender: TObject);
begin
if not Assigned(MyClientThreadthen
MyClientThread:= TMyClientThread.Create('192.168.1.45', 23);
end;

//Отключаемся
procedure TForm1.Button2Click(Sender: TObject);
begin
if Assigned(MyClientThread) then
MyClientThread.Stoped;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Button2Click(nil);
end;

end.
Не получается прочитать данные =(
Все компилируется, но
procedure TMyClientThread.Recieve не выполняется.

Вот код, вдруг что-то не так делаю

unit proj_tcp;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
Vcl.StdCtrls, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer,
IdTCPConnection, IdTCPClient, Vcl.ExtCtrls, IdContext, IdTelnetServer,
IdTelnet, IdAntiFreezeBase, Vcl.IdAntiFreeze;

type
TForm1 = class(TForm)
Memo1: TMemo;
IdTCPClient1: TIdTCPClient;
Opn_clnt_btn: TButton;
Clse_cln_btn: TButton;
IdAntiFreeze1: TIdAntiFreeze;
procedure Opn_clnt_btnClick(Sender: TObject);
procedure Clse_cln_btnClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);


private
{ Private declarations }
public
{ Public declarations }
end;

type
TMyClientThread = class(TThread)
private
FIdTCPClient: TIdTCPClient;
FStrRecieve: string;
Protected
procedure Execute; Override;
procedure Recieve; virtual;
public
constructor Create(Ip: string; Port: Integer); virtual;
destructor Destroy; override;
procedure Stoped; virtual;
procedure OnStop; virtual;
end;

var
Form1: TForm1;
MyClientThread: TMyClientThread=nil;

implementation

{$R *.dfm}

constructor TMyClientThread.Create(Ip: string; Port: Integer);
begin
inherited Create(false);
FreeOnTerminate := True;
FIdTCPClient:= TIdTCPClient.Create(nil);
FIdTCPClient.Host:= Ip;
FIdTCPClient.Port:= Port;
end;

destructor TMyClientThread.Destroy;
begin
Synchronize(OnStop);
FreeAndNil(FIdTCPClient);
MyClientThread:= nil;
inherited;
end;

procedure TMyClientThread.OnStop;
begin
Form1.Memo1.Lines.Add('Stop ' + FIdTCPClient.Host);
end;

procedure TMyClientThread.Recieve; // эта процедура не выполняется
begin
Form1.Memo1.Lines.Add('wait Recieve');
Form1.Memo1.Lines.Add(FStrRecieve);
end;

procedure TMyClientThread.Stoped;
begin
Terminate;
FIdTCPClient.Socket.Binding.CloseSo cket;
end;

procedure TMyClientThread.Execute;
begin
FIdTCPClient.Connect;
Form1.Memo1.Lines.Add('wait execute');
//Проверяем наше соединение
if not FIdTCPClient.Socket.Connected then
exit;
//Если соединение есть то ждем данные
while not Terminated do
begin
FStrRecieve:= FIdTCPClient.Socket.ReadLn;
if FStrRecieve <> '' then
Synchronize(Recieve);
end;

end;


procedure TForm1.Clse_cln_btnClick(Sender: TObject);
begin
if Assigned(MyClientThread) then
MyClientThread.Stoped;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Clse_cln_btnClick(nil);
end;

procedure TForm1.Opn_clnt_btnClick(Sender: TObject);
begin
if not Assigned(MyClientThread) then
MyClientThread:= TMyClientThread.Create('192.168.1.4 5', 23);

end;



end.
Fox78 вне форума Ответить с цитированием
Старый 01.04.2017, 09:54   #9
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

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

Подправьте эту функцию
Код:
procedure TMyClientThread.Execute;
begin
  FIdTCPClient.Connect;
//Проверяем наше соединение
if not FIdTCPClient.Socket.Connected then
exit;

FIdTCPClient.SendCmd(#13#10);
//Если соединение есть то ждем данные
while not Terminated do
begin
  FStrRecieve:= FIdTCPClient.Socket.ReadLn;
  if FStrRecieve <> '' then
  Synchronize(Recieve);
end;

end;
Если не получиться то думаю стоит обратить внимание на компонент TClientSocket должен быть во вкладке internet с ним проще работать
Если у вас в Delphi не установлен этот компонент то с ним можно работать так
Подключаем модуль в Uses ScktComp
Код:
type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
// Если компонент не установлен то прописываем это
    ClientSocket1: TClientSocket;
    procedure ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
    procedure ClientSocketError(Sender: TObject;Socket: TCustomWinSocket;
    ErrorEvent: TErrorEvent; var ErrorCode: Integer);
   procedure ClientSocketDisconnect(Sender: TObject; Socket: TCustomWinSocket);
   procedure ClientSocketConnecting(Sender: TObject; Socket: TCustomWinSocket);
   procedure ClientSocketConnect(Sender: TObject; Socket: TCustomWinSocket);
   procedure ClientSocketWrite(Sender: TObject; Socket: TCustomWinSocket);
  end;

var
  Form1: TForm1;


implementation

{$R *.dfm}

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Button2Click(nil);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
// Если компонент не установлен то прописываем это
ClientSocket1:= TClientSocket.Create(nil);
ClientSocket1.OnConnecting:= ClientSocketConnecting;
ClientSocket1.OnConnect:= ClientSocketConnect;
ClientSocket1.OnDisconnect:= ClientSocketDisconnect;
ClientSocket1.OnError:= ClientSocketError;
ClientSocket1.OnRead:= ClientSocketRead;
ClientSocket1.OnWrite:= ClientSocketWrite;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
// Если компонент не установлен то прописываем это
ClientSocket1.Destroy;
end;

//Подключаемся
procedure TForm1.Button1Click(Sender: TObject);
begin
ClientSocket1.Address:= '192.168.1.45';
ClientSocket1.Port:= 23;
ClientSocket1.ClientType:= ctNonBlocking;
ClientSocket1.Open;
end;

//Отключаемся
procedure TForm1.Button2Click(Sender: TObject);
begin
ClientSocket1.Close;
end;

procedure TForm1.ClientSocketConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
Form1.Memo1.Lines.Add('Connect to ' + ClientSocket1.Address);
//Делаем запрос при подключении если нужно
Socket.SendText(#13#10);
end;

procedure TForm1.ClientSocketConnecting(Sender: TObject; Socket: TCustomWinSocket);
begin
Form1.Memo1.Lines.Add('Connecting to ' + ClientSocket1.Address);
end;

procedure TForm1.ClientSocketDisconnect(Sender: TObject; Socket: TCustomWinSocket);
begin
Form1.Memo1.Lines.Add('Disconnect to ' + ClientSocket1.Address);
end;

procedure TForm1.ClientSocketError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
Form1.Memo1.Lines.Add(Format('Error to %s  %s', [ClientSocket1.Address, SysErrorMessage(ErrorCode)]));
ErrorCode:= 0; //чтобы не останавливала программу при ошибоках в сокете
end;

procedure TForm1.ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
begin
Form1.Memo1.Lines.Add('Read to ' + Socket.ReceiveText);
end;

procedure TForm1.ClientSocketWrite(Sender: TObject; Socket: TCustomWinSocket);
begin
Form1.Memo1.Lines.Add('Write to ' + Socket.ReceiveText);
end;

Последний раз редактировалось Aliens_wolfs; 01.04.2017 в 11:39.
Aliens_wolfs вне форума Ответить с цитированием
Старый 01.04.2017, 11:00   #10
Fox78
Пользователь
 
Регистрация: 17.03.2017
Сообщений: 28
По умолчанию

Цитата:
Сообщение от Aliens_wolfs Посмотреть сообщение
значит нужно послать команду чтобы вам ответил тот ip к которому подключаетесь возможно команду Enter либо нет подключения к этому ip

Если не получиться то думаю стоит обратить внимание на компонент TClientSocket с ним проще работать
Данные приходят без команды, устройство - считыватель кода.
Я проверил и вариант с посылкой FIdTCPClient.SendCmd(#13#10), не работает =(

Для проверки данных, которые с него приходят я скачал терминал hercules_3-2-8.
Выбираю вкладку TCP Client, задаю IP, Port, нажимаю Connect, происходит соединение и клиент ждет данные. Когда сканер считывает данные, клиент ловит их. Прилагаю скриншоты.

P.S. адрес поменял при настройке сканера (на 78), коннектюсь везде с ним
Изображения
Тип файла: jpg 1.jpg (76.8 Кб, 108 просмотров)
Тип файла: jpg 2.jpg (83.2 Кб, 110 просмотров)
Тип файла: jpg 3.jpg (90.1 Кб, 106 просмотров)
Fox78 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Терминал Помощь. everlest Общие вопросы Delphi 2 19.01.2015 09:50
терминал Microlot gugushka Компьютерное железо 0 19.10.2012 11:31
Терминал Линукс! Necare Помощь студентам 3 20.04.2011 17:22
как создать TCP клиент, TCP сервер ? DreamMaster911 C/C++ Сетевое программирование 1 26.10.2010 15:05