Я пытаюсь читать данные в реальном времени, отправляемые с сервера каждые 4 мс. Я использую TCPclinet в Delphi 10.4 и Indy 10 для кроссплатформенного приложения. Все коммуникации между клиентом и сервером основаны на тексте и HTML. На сервере работает веб-сервер (порт 80) и веб-сокет (порт 81). Сервер показывает страницу, которая ожидает отправки 1, а затем начинает отправку данных через сокет. Это работает в TwebBrowser1, и я вижу данные. Я также протестировал свой веб-сокет, используя расширение Chrome, и, похоже, он отправляет данные, как ожидалось (https://chrome.google.com/webstore/detail/websocket-test-client/fgponpodhbmadfljofbimhhlengambbn?hl=en). Однако я не получаю никаких данных в моем сокете на клиенте, используя приведенный ниже код на основе ссылок здесь Delphi: Indy TIdTCPClient для чтения данных и редактирования Реми, а также его обновления здесь https://en.delphipraxis.net/topic/1010-using-indy-for-cross-platform-tcpip/. Также, чтобы получить структуру потока, я использовал здесь ответ Реми Indy TIdTCPClient для получения текста. Исправлен код на основе большего количества чтения, чтобы не вызывать основную угрозу пользовательского интерфейса для ответа на отладочное чтение.
Любая помощь в том, где я ошибаюсь, будет очень признательна.
unit Mainunit;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Memo.Types,
FMX.StdCtrls, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo
,IdCustomTransparentProxy, IdSocks, IdBaseComponent,
IdComponent, IdIOHandler, IdIOHandlerSocket, IdIOHandlerStack,
IdTCPConnection, IdTCPClient, IdSync, FMX.WebBrowser
,Web.HTTPApp, IdHTTP;
type
TDataEvent = procedure(const Data: string) of object;
TReadingThread = class(TThread)
private
FClient : TIdTCPClient;
Fdata: string;
FOnData: TDataEvent;
procedure DataReceived;
protected
procedure Execute; override;
procedure DoTerminate; override;
public
constructor Create(AClient: TIdTCPClient); reintroduce;
property OnData: TDataEvent read FOnData write FOnData;
end;
TLog = class(TIdSync)
protected
FMsg: String;
procedure DoSynchronize; override;
public
constructor Create(const AMsg: String);
class procedure AddMsg(const AMsg: String);
end;
TMainForm = class(TForm)
Memo1: TMemo;
Connect_btn: TButton;
IdTCPClient1: TIdTCPClient;
Disconnect_btn: TButton;
WebBrowser1: TWebBrowser;
refresh_btn: TButton;
procedure DataReceived(const Data: string);
procedure CreateTCPIPConnection;
procedure Connect_btnClick(Sender: TObject);
procedure Disconnect_btnClick(Sender: TObject);
procedure refresh_btnClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
request_count : integer;
end;
var
MainForm: TMainForm;
ZPReadThread: TReadingThread = nil;
implementation
{$R *.fmx}
procedure TMainForm.CreateTCPIPConnection;
begin
if not Assigned(ZPReadThread) then
begin
IdTCPClient1.Host := '192.168.11.5';
IdTCPClient1.Port := 81;
try
ZPReadThread := TReadingThread.Create(IdTCPClient1);
try
ZPReadThread.OnData := DataReceived;
ZPReadThread.Start;
except
FreeAndNil(ZPReadThread);
raise;
end;
except
on E: Exception do
begin
TLog.AddMsg('DEBUG: TCP/IP exception creating read thread : '+E.Message);
end;
end;
end;
end;
constructor TReadingThread.Create(AClient: TIdTCPClient);
begin
TLog.AddMsg('DEBUG: TReadingThread.Create');
inherited Create(True);
FClient := AClient;
end;
procedure TReadingThread.Execute;
begin
try
FClient.ConnectTimeout := 10000; // <-- use whatever you want... was 10000
FClient.Connect;
if FClient.Connected then
TLog.AddMsg('DEBUG: Threat execute connected to the client: ' + FClient.Host
+ ' on port: ' + inttostr(FClient.Port)
+ ' RecvBufferSize: ' + inttostr(FClient.IOHandler.RecvBufferSize)
);
except
on E: Exception do
begin
TLog.AddMsg('DEBUG: TCP/IP connect exception : '+E.Message);
raise;
end;
end;
try
FClient.IOHandler.ReadTimeout := 1000; // <-- use whatever you want... was 5000
while not Terminated do
begin
try
FData := FClient.IOHandler.ReadLn();
except
on E: Exception do
begin
TLog.AddMsg('DEBUG: TCP/IP IOHandler.ReadLn exception : '+E.Message);
raise;
end;
end;
// if (FData <> '') and Assigned(FOnData) then Synchronize(DataReceived);
Synchronize(DataReceived);
SetLength (FData,0);
end;
finally
FClient.Disconnect;
end;
end;
procedure TReadingThread.DataReceived;
begin
if Assigned(FOnData) then FOnData(FData);
Mainform.request_count := Mainform.request_count + 1;
TLog.AddMsg('Debug: ' + inttostr(MainForm.request_count)+ ' ) Inside proc DataRecieved of thread fdata is: ' + FData);
end;
procedure TReadingThread.DoTerminate;
begin
TLog.AddMsg('Debug: Read thread terminating');
inherited;
end;
constructor TLog.Create(const AMsg: String);
begin
inherited Create;
FMsg := AMsg;
end;
procedure TLog.DoSynchronize;
begin
Mainform.Memo1.Lines.Add(FMsg);
end;
class procedure TLog.AddMsg(const AMsg: String);
begin
with Create(AMsg) do
try
Synchronize;
finally
Free;
end;
end;
procedure TMainForm.DataReceived(const Data: string);
begin
Memo1.Lines.Add('Recevied data DataRecieved of form : ' + Data);
end;
procedure TMainForm.Connect_btnClick(Sender: TObject);
begin
try
WebBrowser1.Navigate('http://192.168.11.5/');
CreateTCPIPConnection();
request_count := 0;
except
on E: Exception do
MainForm.Memo1.Lines.Add('Threat connection Error: ' + E.Message);
end;
end;
procedure TMainForm.Disconnect_btnClick(Sender: TObject);
begin
if Assigned(ZPReadThread) then
begin
TLog.AddMsg('Debug: Terminating Read thread');
ZPReadThread.Terminate;
TLog.AddMsg('Debug:Waiting for read thread termination');
ZPReadThread.WaitFor;
TLog.AddMsg('Debug:Finished waiting for read thread termination');
FreeAndNil(ZPReadThread);
end
else TLog.AddMsg('Debug:Thread not active');
end;
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Disconnect_btnClick(Sender);
end;
procedure TMainForm.refresh_btnClick(Sender: TObject);
begin
WebBrowser1.Reload;
memo1.Lines.clear;
request_count := 0;
end;
end.