android-TIdIOHandler.Write过程无法在移动设备上运行

android-TIdIOHandler.Write过程无法在移动设备上运行,第1张

概述我正在尝试将流从移动设备(iOS,Android)发送到TCPServer.对于服务器和客户端,我正在使用Indy组件.当我尝试从移动设备中运行的FMX应用程序发送流时​​,会发生此问题.如果我从Windows运行客户端代码,则客户端会将流发送到ServerApp.但是我从移动设备上运行了相同的代码,但未发送

我正在尝试将流从移动设备(iOS,Android)发送到TCP Server.对于服务器和客户端,我正在使用Indy组件.

当我尝试从移动设备中运行的FMX应用程序发送流时​​,会发生此问题.如果我从windows运行客户端代码,则客户端会将流发送到Server App.但是我从移动设备上运行了相同的代码,但未发送流.

这是服务器和客户端的最小,完整和可验证的示例,可以重现此问题.

服务器端 .该服务器是VCL应用程序.

unit uServer;interfaceuses  WinAPI.windows, WinAPI.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IDBaseComponent, IDComponent,  IDCustomTcpserver, IDTcpserver, Vcl.StdCtrls, IDContext;type  TFrmServer = class(TForm)    IDTcpserver1: TIDTcpserver;    Memolog: TMemo;    procedure FormCreate(Sender: TObject);    procedure IDTcpserver1Execute(AContext: TIDContext);  private    { Private declarations }  public    { Public declarations }  end;var  FrmServer: TFrmServer;implementationuses  IDGlobal,  IdioHandler,  System.StrUtils;{$R *.dfm}procedure TFrmServer.FormCreate(Sender: TObject);begin  IDTcpserver1.Bindings.Clear;  IDTcpserver1.DefaultPort := 28888;  IDTcpserver1.Active := True;  Memolog.lines.Add('Running');end;procedure TFrmServer.IDTcpserver1Execute(AContext: TIDContext);var  LHandler  : TIdioHandler;  s: string;  LMemoryStream : TMemoryStream;  AFormatSettings: TFormatSettings;  d : Int64;begin  try    LHandler := AContext.Connection.IOHandler;    s := LHandler.ReadLn(LF, IDTimeoutDefault, MaxInt);    AFormatSettings := TFormatSettings.Create;    if (s <> '') then    begin       if StartsText('<',  s) and EndsText('>',  s)  then       begin            TThread.Queue(nil,              procedure              begin                Memolog.lines.Add(Format('%s', [s], AFormatSettings));              end            );            LMemoryStream := TMemoryStream.Create;            try                LHandler.LargeStream := True;                LHandler.ReadStream(LMemoryStream, -1, False);                d := LMemoryStream.Size;                TThread.Queue(nil,                  procedure                  begin                    Memolog.lines.Add(Format('Stream Size %d', [d], AFormatSettings));                  end                );            finally              LMemoryStream.Free;            end;       end       else         LHandler.inputBuffer.Clear;    end;  except    on E: Exception do    begin      s := E.Message;      TThread.Queue(nil,        procedure        begin          Memolog.lines.Add(Format('Exception %s', [s], AFormatSettings));        end      );    end;  end;end;end.

客户端(FMX应用程序)

unit uClIEnt;interfaceuses  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,  IDBaseComponent, IDComponent, IDTCPConnection, IDTCPClIEnt, FMX.ScrollBox,  FMX.Memo, FMX.Controls.Presentation, FMX.StdCtrls;type  TFrmClIEnt = class(TForm)    IDTCPClIEnt1: TIDTCPClIEnt;    button1: Tbutton;    Memolog: TMemo;    procedure FormCreate(Sender: TObject);    procedure button1Click(Sender: TObject);  private    procedure Send;  public    { Public declarations }  end;var  FrmClIEnt: TFrmClIEnt;implementation{$R *.fmx}type  TSendThread = class(TThread)  private    FTCPClIEnt : TIDTCPClIEnt;  public    procedure Execute; overrIDe;    constructor Create(ATCPClIEnt : TIDTCPClIEnt); reintroduce;  end;procedure TFrmClIEnt.button1Click(Sender: TObject);begin   Send;end;procedure TFrmClIEnt.FormCreate(Sender: TObject);begin try  IDTCPClIEnt1.Port := 28888;  IDTCPClIEnt1.Host := '192.168.1.134'; //change this to the ip of the  TCP server.  IDTCPClIEnt1.ConnectTimeout := 5000;  IDTCPClIEnt1.Connect();  Memolog.lines.Add('Connected');  except on E: Exception do     Memolog.lines.Add('Exception ' + E.Message); end;end;procedure TFrmClIEnt.Send;begin  if IDTCPClIEnt1.Connected then    TSendThread.Create(IDTCPClIEnt1);end;{ TSendThread }constructor TSendThread.Create(ATCPClIEnt: TIDTCPClIEnt);begin  inherited Create(False);  FTCPClIEnt := ATCPClIEnt;end;procedure TSendThread.Execute;var  LStream : TStream;  d : Int64;begin   LStream := TMemoryStream.Create;   try     //Send a text from all the platforms works perfect.     FTCPClIEnt.IOHandler.WriteLn('<Hello>');     LStream.Size := 1024;     LStream.position := 0;     d := LStream.Size;     FTCPClIEnt.IOHandler.LargeStream := True;     //this only works from windows     FTCPClIEnt.IOHandler.Write(LStream,  d, True);   finally     LStream.Free;   end;end;end.

问题是,如何使用Indy组件从移动设备发送流?

更新:

AndroID权限

<uses-permission androID:name="androID.permission.ACCESS_WIFI_STATE" /><uses-permission androID:name="androID.permission.INTERNET" /><uses-permission androID:name="androID.permission.READ_EXTERNAL_STORAGE" /><uses-permission androID:name="androID.permission.READ_PHONE_STATE" /><uses-permission androID:name="androID.permission.WRITE_EXTERNAL_STORAGE" />

解决方法:

最终,我发现了这个问题,我误以为没有发送数据,发送了流,但是服务器无法处理流,因为TIdioHandler.ReadStream函数无法正确读取流的大小.在AByteCount参数中传递-1值时,会发生这种情况.然后,使用TIdioHandler.ReadInt64或TIdioHandler.ReadInt32函数读取流的大小,并且在内部,这些函数试图使用GStack.NetworkToHost函数转换整数的字节序.

我解决了读取流大小而不转换字节序的问题.

我替换了这条线

LHandler.ReadStream(LMemoryStream, -1, False);

对于此代码

LHandler.LargeStream := True;LHandler.ReadBytes(LBytes, SizeOf(Int64), False);d := BytesToInt64(LBytes);LHandler.ReadStream(LMemoryStream, d, False);
总结

以上是内存溢出为你收集整理的android-TIdIOHandler.Write过程无法在移动设备上运行全部内容,希望文章能够帮你解决android-TIdIOHandler.Write过程无法在移动设备上运行所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1120906.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-29
下一篇 2022-05-29

发表评论

登录后才能评论

评论列表(0条)

保存