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!