LAMW Http-TCP server with Lnet
lazarus / 43-Android
----------------------------------------------------------------------
benohb · 2021-06-30 22:31
This is the minimal code for making a Http / TCP server using the INET
library with LAMW ...Did we forget something
Note: The lnet library (lnetvisual.lpk) cannot be built … Use only
the package lnetbase.lpk
You don't need to rebuild Lazarus . Just add a package lnetbase.lpk
to your project
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i unit
unit1;{$mode objfpc}{$H+}interfaceuses Classes, SysUtils,
AndroidWidget, Laz_And_Controls,lNet;type { TAndroidModule1 }
TAndroidModule1 = class(jForm) jButton1: jButton; jTimer1:
jTimer; FCon: TLTCP; procedure AndroidModule1Create(Sender:
TObject); procedure AndroidModule1Destroy(Sender: TObject);
procedure jButton1Click(Sender: TObject); procedure
jTimer1Timer(Sender: TObject); private procedure OnRe(aSocket:
TLSocket); public {public declarations} end;var AndroidModule1:
TAndroidModule1; implementation {$R *.lfm} { TAndroidModule1
}procedure TAndroidModule1.AndroidModule1Create(Sender:
TObject);begin FCon := TLTCP.Create(nil); // create new TCP
connection FCon.OnReceive := @OnRe; FCon.Timeout := 100; //
responsive enough, but won't hog cpu FCon.ReuseAddress := True;
FCon.Listen(8000); end;procedure
TAndroidModule1.AndroidModule1Destroy(Sender: TObject);begin
FCon.Free; inherited Destroy;end;procedure
TAndroidModule1.jButton1Click(Sender: TObject);begin
jTimer1.Enabled:=true;end;procedure
TAndroidModule1.jTimer1Timer(Sender: TObject);begin
FCon.CallAction;end;procedure TAndroidModule1.OnRe(aSocket:
TLSocket);var s,OutputDataString: string; n: Integer;begin if
aSocket.GetMessage(s) > 0 then begin // if we received anything
(result is in s) FCon.IterReset; // now it points to server socket
while FCon.IterNext do begin // while we have clients to echo to
OutputDataString := '' +
#13#10 + '
Teste
' + #13#10;
FCon.SendMessage('HTTP/1.0 200' + #13#10);
FCon.SendMessage('Content-type: Text/Html' + #13#10);
FCon.SendMessage('Content-length: ' +
IntToStr(Length(OutputDataString)) + #13#10);
FCon.SendMessage('Connection: keep-alive' + #13#10);
FCon.SendMessage('Date: ' +'Thu, 06 Dec 2018 17:37:18 GMT' + #13#10);
FCon.SendMessage('Server: Lazarus Inet' + #13#10);
FCon.SendMessage('' + #13#10);
FCon.SendMessage(OutputDataString); end; end;end;end.
----------------------------------------------------------------------
Mongkey · 2021-06-30 23:23
, Awesome, thank you, but anyway not work, got error on
fcon.listen(port).
I tried this one:
https://wiki.freepascal.org/Light_Web_Server
Worked, but freezing.
----------------------------------------------------------------------
Mongkey · 2021-07-02 04:56
Waiting loaded or JMPessoa to solve
----------------------------------------------------------------------
benohb · 2021-07-10 08:33
Quote from: Mongkey on July 01, 2021, 01:23:01 am
, Awesome, thank you, but anyway not work, got error on
fcon.listen(port).
It has been working well...then a problem appeared
I tried to understand where the problem is
QuoteI tried this one:
https://wiki.freepascal.org/Light_Web_Server
Worked, but freezing.
Yes...I'm avoiding this library
I think this example works fine
QuoteLAMW/lamw4linux/usr/share/fpcsrc/release_3_2_2/packages/fcl-
web/examples/httpserver/simplehttpserver.pas
----------------------------------------------------------------------
benohb · 2021-07-10 08:36
Quote from: Mongkey on July 02, 2021, 06:56:40 am
Waiting loaded or JMPessoa to solve
I don't understand... please explain
----------------------------------------------------------------------
jmpessoa · 2021-07-10 14:03
QuoteI don't understand... please explain
Hi, benohb!
Please, help here!
----------------------------------------------------------------------
benohb · 2021-07-11 00:32
hhhhhh lol
I figured "jmpessoa" as class or component
Hello jmpessoa
What do you think about the matter?
QuoteLAMW/lamw4linux/usr/share/fpcsrc/release_3_2_2/packages/fcl-
web/examples/httpserver/simplehttpserver.pas
I have another problem (linux)"adb install " is executed before
building a package
apkbuild.pas/(RunExternalTool(Tool)) Called twice without sequence of
steps
----------------------------------------------------------------------
Guser979 · 2021-08-08 00:15
My best experience with TCP was using this example:
https://forum.lazarus.freepascal.org/index.php/topic,48677.msg397515.h
tml#msg397515....
My initial need was to upload files from my phone to the example
desktop server.
In my case, to test, I copied all units (.pas) and *.inc from Synapse
40 to a project's JNI folder (APPTCPClientDemo )
http://www.ararat.cz/synapse/doku.php/download
Then I added in 'uses' : blcksock, uTCPSockets, uTCPCryptoCompression
I just used parts of the Synapse TCP/IP client and server code (by
GETMEM ) to send and receive messages and files.
It worked very well integrating mobile and desktop apps.
Synapse's compatibility with LAWM is excellent.With the GETMEM code
practically everything is done.
Just study Getmem's work and do what you want
Good luck.
A fragment to help. With this it is possible to connect to the server,
send files and messages. Just improve, including handling errors and
more
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i {$mode
delphi}unit unit1;interface uses Classes, SysUtils, And_jni,
And_jni_Bridge, Laz_And_Controls, Laz_And_Controls_Events,
AndroidWidget, opendialog, blcksock, uTCPSockets,
uTCPCryptoCompression,fileutil; type { TAndroidModule1 }
TAndroidModule1 = class(jForm) jAsyncTask1: jAsyncTask;
jButton1: jButton; jButton2: jButton; jButton3: jButton;
jEditText1: jEditText; jEditText2: jEditText; jOpenDialog1:
jOpenDialog; procedure AndroidModule1JNIPrompt(Sender: TObject);
procedure AndroidModule1RequestPermissionResult(Sender: TObject;
requestCode: integer; manifestPermission: string; grantResult:
TManifestPermissionResult); procedure
jAsyncTask1DoInBackground(Sender: TObject; progress: integer; out
keepInBackground: boolean); procedure
jAsyncTask1PostExecute(Sender: TObject; progress: integer);
procedure jButton1Click(Sender: TObject); procedure
jButton2Click(Sender: TObject); procedure jButton3Click(Sender:
TObject); procedure jOpenDialog1FileSelected(Sender: TObject; path:
string; fileName: string); private public {public
declarations} function SendMessage(AMsg: String; AParams:
array of String): Boolean; function RecvMessage(ATimeOut:
Integer; out AMsgTyp: Integer; out AMsg: String; out AParams:
TStringArray): Boolean; procedure DoError(AErrMsg: String;
AErrCode: Integer); function DoTask(Progress: integer):
boolean; function SendFile(AFileName: String): Boolean;
end; var AndroidModule1: TAndroidModule1; FBlockSocket :
TTCPBlockSocket; MsgTyp:integer; Msg:string;
Params:tstringarray;implementation {$R *.lfm}
//To connect to
the GetMem server procedure TAndroidModule1.jButton1Click(Sender:
TObject); begin FBlockSocket :=
TTCPBlockSocket.Create; FBlockSocket.Connect ('172.26.61.98',
'53771');//the ip here is a node of a network I created with Zerotier.
// No password in server . Please FBlockSocket.SendString
(encrypt('53771','0LOGIN:,User,0,') ); repeatuntil RecvMessage(500,
MsgTyp, Msg, Params) ; jEditText2.Text :=Params[0];jAsyncTask1.Execute
;end; // send text message : procedure
TAndroidModule1.jButton2Click(Sender: TObject); begin
SendMessage('0TEXT', [jEditText1.Text]); End; //Choose a
fileprocedure TAndroidModule1.jButton3Click(Sender: TObject); begin
jOpenDialog1.Show();end; //Send file procedure
TAndroidModule1.jOpenDialog1FileSelected(Sender: TObject; path:
string; fileName: string);begin SendMessage('2FILE',
['FILE',inttostr( fileutil.FileSize(path+'/'+fileName)),fileName]);
SendFile(path+'/'+fileName); end; //GetMem Code
Functionsfunction TAndroidModule1.SendFile(AFileName: String):
Boolean;var ReadCnt: LongInt; Cnt: Int64; Buffer: Pointer; MS:
TMemoryStream; MSComp: TMemoryStream; FS: TFileStream; Msg:
String; CompRate: Single;begin Result := False; try FS :=
TFileStream.Create(AFileName, fmOpenRead or fmShareDenyWrite); try
FS.Position := 0; GetMem(Buffer, FBlockSocket.SendMaxChunk);
try Cnt := 0; MS := TMemoryStream.Create;
try MSComp := TMemoryStream.Create; try
repeat Msg := FBlockSocket.RecvPacket(50000);
if (FBlockSocket.LastError > 0) or (Msg = 'DONE') or (Msg <> 'NEXT')
then Break; ReadCnt := FS.Read(Buffer^,
FBlockSocket.SendMaxChunk); if (ReadCnt > 0) then
begin MS.Clear; MS.Write(Buffer^,
ReadCnt); MS.Position := 0;
FBlockSocket.SendStream(MS); if (FBlockSocket.LastError = 0)
then begin Cnt := Cnt + MS.Size;
end; end; until (ReadCnt = 0) or
(Cnt > FS.Size); Result := FBlockSocket.LastError = 0;
if Result then showmessage(inttostr(FS.Size)) else
showmessage('erro'); finally MSComp.Free;
end; finally MS.Free; end; finally
FreeMem(Buffer); end; finally FS.Free; end; except
on E: Exception do showmessage('erro'); endend; function
TAndroidModule1.SendMessage(AMsg: String; AParams: array of String):
Boolean;var I: Integer; Msg: String;begin Result := False; Msg :=
AMsg; if Length(AParams) > 0 then begin AMsg := AMsg + ':';
for I := Low(AParams) to High(AParams) do AMsg := AMsg +
AParams[I] + ','; end; AMsg := Encrypt('53771', AMsg);
FBlockSocket.SendString(AMsg); Result := FBlockSocket.LastError = 0;
Delete(Msg, 1, 1); if Result then showmessage('Send') else
showmessage('error');end; function
TAndroidModule1.RecvMessage(ATimeOut: Integer; out AMsgTyp: Integer;
out AMsg: String; out AParams: TStringArray): Boolean;var Str:
String; P: Integer; Len: Integer; var
m:tmemorystream;begin Result :=true; AMsg := ''; AMsgTyp := -1;
AParams := nil; Str := FBlockSocket.RecvPacket(ATimeOut); if
(FBlockSocket.LastError > 0) then begin Result := False; Exit;
end; if Trim(Str) <> '' then begin Str := Decrypt('53771', Str);
P := Pos(':', Str); if P > 0 then begin AMsg :=
Trim(System.Copy(Str, 1, P - 1)); System.Delete(Str, 1, P);
repeat P := Pos(',', Str); if P > 0 then begin
Len := Length(AParams); SetLength(AParams, Len + 1);
AParams[Len] := System.Copy(Str, 1, P - 1);
System.Delete(Str, 1, P); end; until (P = 0) or (Str = '')
; end else AMsg := Trim(Str); AMsgTyp :=
StrToIntDef(AMsg[1], -1); if (not AMsgTyp in [0..3]) then
begin jEditText2.Text :='Error'; Result := False;
Exit; end;Delete(AMsg, 1, 1); end;end;
//jAsyncTaskfunction TAndroidModule1.DoTask(Progress: integer):
boolean; begin Result:= True; repeat until RecvMessage(500,
MsgTyp, Msg, Params) ; Result:= False;end; procedure
TAndroidModule1.jAsyncTask1DoInBackground(Sender: TObject; progress:
integer; out keepInBackground: boolean);
begin keepInBackground:= DoTask(progress); end; procedure
TAndroidModule1.jAsyncTask1PostExecute(Sender: TObject; progress:
integer);begin jAsyncTask1.Done; jEditText2.Text :=Params[0];
jAsyncTask1.Execute;end; procedure
TAndroidModule1.AndroidModule1JNIPrompt(Sender: TObject);var
manifestPermissions: TDynArrayOfString; begin if
IsRuntimePermissionNeed() then // that is, target API >= 23
begin SetLength(manifestPermissions, 3);
manifestPermissions[1]:= 'android.permission.WRITE_EXTERNAL_STORAGE';
//from AndroodManifest.xml
Self.RequestRuntimePermission(manifestPermissions, 1001);
SetLength(manifestPermissions, 0); end; end; procedure
TAndroidModule1.AndroidModule1RequestPermissionResult( Sender:
TObject; requestCode: integer; manifestPermission: string;
grantResult: TManifestPermissionResult);begin case requestCode
of 1001:begin if grantResult =
PERMISSION_GRANTED then exit; end; end; end;
// insert as the code asks for jButton
jEditText jAsyncTask // And of course, declare variables etc as the
code asks for // don't forget the necessary permissions.
Note: This was my first test and I used APPTCPClientDemo from LAMW. I
suggest using the code above in the demo cited to test. Add necessary
permission to read files.
Edit : I just tested this by starting a new project and noticed there
were some bugs. Have been fixed.
Edit2 : This code is old. I don't recommend using jAsyncTask because
its behavior is unstable. When I used this, it worked. But that was a
long time ago..
Edit3 :
Finally some free time.
removed JaSynctask and use jTCPSocketClient to send and receive
strings.
Note: To send files disconnect jTCPSocketClient and connect
TTCPBlockSocket. At the end, connect Tcpclient again.
The "template" is APPTCPClientDemo. The "Stop Client" button sends
files.
Again : This code is mainly for anyone who wants to use GETMEM Demo
with phone. But it serves to make improvements in LAWN TCPIP. Get to
work...
The code needs to get cleaned up. There's a lot of unnecessary stuff.
They are experiments. But... it works,
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i {Hint:
save all files to location:
C:\adt32\eclipse\workspace\AppTCPClientDemo1\jni }unit unit1;{$mode
delphi}// {$mode objfpc}{$H+}interfaceuses Classes, SysUtils,
And_jni, And_jni_Bridge, Laz_And_Controls, Laz_And_Controls_Events,
AndroidWidget, tcpsocketclient, textfilemanager, opendialog,
blcksock, uTCPSockets, uTCPCryptoCompression, strutils, fileutil,
uSettings;type { TAndroidModule1 } TAndroidModule1 = class(jForm)
jButton1: jButton; jButton2: jButton; jButton3: jButton;
jEditText1: jEditText; jEditText2: jEditText; jOpenDialog1:
jOpenDialog; jTCPSocketClient1: jTCPSocketClient; jTextView1:
jTextView; jTextView2: jTextView; jTextView3: jTextView;
procedure AndroidModule1JNIPrompt(Sender: TObject); procedure
AndroidModule1RequestPermissionResult(Sender: TObject;
requestCode: integer; manifestPermission: string; grantResult:
TManifestPermissionResult); procedure jButton1Click(Sender:
TObject); procedure jButton2Click(Sender: TObject); procedure
jButton3Click(Sender: TObject); procedure
jOpenDialog1FileSelected(Sender: TObject; path: string; fileName:
string); procedure jTCPSocketClient1Connected(Sender: TObject);
procedure jTCPSocketClient1MessagesReceived(Sender: TObject;
messageReceived: string); private {private declarations}
FConnected: boolean; sock,FBlockSocket, c,s :TTCPBlockSocket;
FNeedToClose: Boolean; FTCPClient: TTCPClient; FSettings:
TSettings; FConCap: String; FDisCap: String; FTCPBase:
TTCPBase; FTCPBaseType: TBaseType; FConnection: TConnection;
var Msg: String; MsgTyp: Integer; Params: TStringArray; Size:
Int64; MS: TMemoryStream; // I: Integer; FileName,tim,str,f:
String; Path: String; TmpTaskList: TList; FCurPing: QWord;
res,can:boolean; public {public declarations} property
Connection: TConnection read FConnection; function
SendFile(AFileName: String): Boolean; end; var AndroidModule1:
TAndroidModule1; implementation{$R *.lfm} { TAndroidModule1
} function TAndroidModule1.SendFile(AFileName: String): Boolean;var
ReadCnt: LongInt; Cnt: Int64; Buffer: Pointer;// MS:
TMemoryStream; MSComp: TMemoryStream; FS: TFileStream; fi:boolean;
Mi,si: String; CompRate: Single;begin Result := False; si:=
inttostr(fileutil.FileSize(afilename)); mi:=
'2FILE:FILE,'+si+','+extractfilename(afilename)+','; mi:=
Encrypt('53771', mi);FBlockSocket.SendString( mi ); try FS :=
TFileStream.Create(AFileName, fmOpenRead or fmShareDenyWrite); try
FS.Position := 0; GetMem(Buffer, FBlockSocket.SendMaxChunk);
try Cnt := 0; MS := TMemoryStream.Create;
try MSComp := TMemoryStream.Create; try
repeat repeat Msg :=
FBlockSocket.RecvPacket(50000); until (Msg = 'DONE') or
(Msg = 'NEXT'); if (FBlockSocket.LastError > 0) or (Msg =
'DONE') or (Msg <> 'NEXT') then begin
showmessage(Msg); Break; end; ReadCnt :=
FS.Read(Buffer^, FBlockSocket.SendMaxChunk); if (ReadCnt
> 0) then begin MS.Clear;
MS.Write(Buffer^, ReadCnt); MS.Position := 0;
FBlockSocket.SendStream(MS); if
(FBlockSocket.LastError = 0) then begin
Cnt := Cnt + MS.Size; end; end;
until (ReadCnt = 0) or (Cnt > FS.Size); Result :=
FBlockSocket.LastError = 0; if Result then begin
FBlockSocket.CloseSocket; jButton1Click(self) end else
showmessage('erro'); finally MSComp.Free;
end; finally MS.Free; end; finally
FreeMem(Buffer); end; finally FS.Free; end; except
on E: Exception do showmessage('erro'); endend; procedure
TAndroidModule1.jButton1Click(Sender: TObject);begin
jEditText2.Clear;
jTCPSocketClient1.ConnectAsync('172.26.61.98',53771);end; procedure
TAndroidModule1.jButton2Click(Sender: TObject);begin jTCPSocketClient1
.SendMessage(Encrypt('53771','0TEXT:'+jEditText1.Text+',')
);end; procedure TAndroidModule1.jButton3Click(Sender: TObject);begin
jTCPSocketClient1.CloseConnection(); FBlockSocket.Connect
('172.26.61.98', '53771');// eua32 = YOUR USERNAME
FBlockSocket.SendString (encrypt('53771','0LOGIN:,eua32,0,') );//
'hello'#13#10);repeat until FBlockSocket.RecvPacket(5000) <> '';
jOpenDialog1.Show();end; procedure
TAndroidModule1.jOpenDialog1FileSelected(Sender: TObject; path:
string; fileName: string);begin f:=
getEnvironmentDirectoryPath(TEnvDirectory.dirDownloads)+'/'+fileName;
SendFile(f);end; procedure
TAndroidModule1.jTCPSocketClient1Connected(Sender: TObject);begin//
eua32 = YOUR USERNAME jTCPSocketClient1.SendMessage(encrypt('53771
','0LOGIN:,eua32,0,'));end; procedure
TAndroidModule1.jTCPSocketClient1MessagesReceived(Sender: TObject;
messageReceived: string);begin messageReceived:=decrypt('53771',
messageReceived); jEditText2.Text :=timetostr(now)+':'+replacestr(ext
ractword(2,messageReceived,[':']),',','');str:='';end; procedure
TAndroidModule1.AndroidModule1JNIPrompt(Sender: TObject); var
manifestPermissions: TDynArrayOfString; var myMenu:
jObjectRef; begin
self.SetStatusColor(androidmodule1.BackgroundColor ); if
IsRuntimePermissionNeed() then // that is, target API >= 23
begin SetLength(manifestPermissions, 3);
manifestPermissions[0]:= 'android.permission.CAMERA'; //from
AndroodManifest.´ manifestPermissions[1]:=
'android.permission.WRITE_EXTERNAL_STORAGE'; //from
AndroodManifest.xml
manifestPermissions[2]:='android.permission.RECORD_AUDIO';
Self.RequestRuntimePermission(manifestPermissions, 1001);
SetLength(manifestPermissions, 0); end; if
IsRuntimePermissionNeed() then //support for "target API >= 23"
begin
Self.RequestRuntimePermission('android.permission.RECORD_AUDIO',
3111); end ;can:=false; res:=false; FBlockSocket :=
TTCPBlockSocket.Create;end; procedure
TAndroidModule1.AndroidModule1RequestPermissionResult( Sender:
TObject; requestCode: integer; manifestPermission: string;
grantResult: TManifestPermissionResult);begin case requestCode
of 1001:begin if grantResult = PERMISSION_GRANTED
then exit// ShowMessage('Success!
['+manifestPermission+'] Permission grant!!! ' ) else
//PERMISSION_DENIED ShowMessage('Sorry...
['+manifestPermission+'] Permission not grant... ' ); end;
end;end;end.
----------------------------------------------------------------------
benohb · 2021-09-17 17:11
Guser979
Sorry for the delay. Thank you. Helpful examples. Thank you
----------------------------------------------------------------------
jmpessoa · 2021-09-17 17:19
Hi, Guser979!
Can you put your TCP demo in some "open drive"?
So, I will commit it to LAMW github....
Thank you!
----------------------------------------------------------------------
Guser979 · 2021-09-18 14:32
Ok, done. AppTCPClientDemo2 .
Tested and working. Synapse dependencies are in the JNI folder
The initial IP is my WIFI.
https://drive.google.com/file/d/190xtdTJUQqqz2Quq_JA8yLwa9G1OJuYV/view
?usp=sharing
Edit : I forgot to clean up the Build/ Intermediates folder. Sorry
about that.
Update : Added entry for port. Sorry, but as I'm not a programmer,
I'm not used to distributing my tools or apps. Only I use them.
JMpessoa, please do what I don't know.
----------------------------------------------------------------------
jmpessoa · 2021-09-19 18:51
QuoteSo, I will commit it to LAMW github....
Done!
New demo "AppTCPClientDemo2"!
Thank you!