我正在尝试将流从移动设备(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过程无法在移动设备上运行所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)