To summarize:Just install the latest version. Most of the issues mentioned above are fixed. You can download the latest version from here: https://svn.atozed.com:444/svn/Indy10 (use a svn client). Alternatively you can install indy with OPM(http://wiki.freepascal.org/Online_Package_Manager)
1. Is there a newer more stable Indy version for Lazarus-Linux and where to get it from? Similarly are there any specific tweaks that should be done during the Indy installation on Lazarus, other than the usual (eg compile the .lpk twice)?
2. Is there any hope to drag the TCPServer widget from the palette onto the Lazarus form without crashing Lazarus?
3. Is there a way to activate my TCPServer instance on Linux-Lazarus without crashing the app?
4. Is there a way to have the correct transliteration with international character sets between a client and a server? In any case this I believe is a secondary issue as I do not plan a Linux to Windows connection but for educational use only.
and perhaps the most important of them all:
5. Do I stand a chance with Linux-Lazarus-Indy or should I have to look elsewhere? Indy is highly reputable and would be glad in case I could overcome my issues. On the other hand Windows and Delphi are not an option other than for fooling around.
To begin with many thanks for your kind responses.
But I still fail to Activate IdTCPServer1 exactly as before with run time message 'RunError(232)'.
Not to mention that as I write code, I get the message:at the message window.
Codetools, Errors: 1 IdGlobal.pas(1889,105) Error: expected:; but deprecated found. refering to line: GOffsetFromUTC: TDateTime = 0{$IFDEF HAS_DEPRECATED}{$IFDEF USE_SEMICOLON_BEFORE_DEPRECATED};{$ENDIF} deprecated{$ENDIF};
What am I doing wrong?
s
Have downloaded Indy version 10.2.0.3 and installed it into Lazarus without issues.
Code: [Select]IdTCPServer1.Bindings.Add.IP := '127.0.0.1';
IdTCPServer1.Bindings.Add.Port := 6000;
Binding := IdTCPServer1.Bindings.Add;
Binding.IP := '127.0.0.1';
Binding.Port := 6000;
with IdTCPServer1.Bindings.Add do
begin
IP := '127.0.0.1';
Port := 6000;
end;
I mean I could send a string in Latin from the Mint-Lazarus demo-client-app to the Windows-Delphi demo-server-app, but I could not find a way to include international characters to the string. Believe this must be a transliteration issue. AFAIK Linux uses UTF8 while Redmond uses UTF16.
Have used:to get the string on the server at the IdTCPServer1Execute OnExecute handler, while similarly I used
LLine := AContext.Connection.IOHandler.ReadLn(TIdTextEncoding.UTF8);at the client to send the string. This did not work.
IdTCPClient1.IOHandler.WriteLn(Edit1.Text, enDefault);
Had some better luck usingat the client side.
IdTCPClient1.IOHandler.WriteLn(Edit1.Text, enUTF8);
While Latin text comes OK, still have failed with international (Greek) chars.
In any case, each and every time I disconnect the client, the server fires the OnException event with message ‘Connection closed gracefully’. Is this an exception really?
1. Is there a newer more stable Indy version for Lazarus-Linux and where to get it from?
2. Is there any hope to drag the TCPServer widget from the palette onto the Lazarus form without crashing Lazarus?
3. Is there a way to activate my TCPServer instance on Linux-Lazarus without crashing the app?
4. Is there a way to have the correct transliteration with international character sets between a client and a server?
5. Do I stand a chance with Linux-Lazarus-Indy or should I have to look elsewhere?
In Linux Version of Indy10, you need to confirm the IPVersion ( id_IPV4 or id_IPv6 )
IdTCPServer1.Bindings.Items[ 0 ].IPVersion := Id_IPv4 ;
You can download the latest version from here: https://svn.atozed.com:444/svn/Indy10 (use a svn client).
But I still fail to Activate IdTCPServer1 exactly as before with run time message 'RunError(232)'.
Not to mention that as I write code, I get the message:at the message window.
Codetools, Errors: 1 IdGlobal.pas(1889,105) Error: expected:; but deprecated found. refering to line: GOffsetFromUTC: TDateTime = 0{$IFDEF HAS_DEPRECATED}{$IFDEF USE_SEMICOLON_BEFORE_DEPRECATED};{$ENDIF} deprecated{$ENDIF};
In the IdGlobal.pas, I just modify as follow and it work for me.
GOffsetFromUTC: TDateTime = 0 ; deprecated ;
{$IFDEF FPC}
...
{$IFDEF FPC_2_4_4_OR_ABOVE}
...
{$IFNDEF FPC_2_6_2_OR_ABOVE}
{$DEFINE USE_SEMICOLON_BEFORE_DEPRECATED} // TODO: which earlier versions require a semicolon?
{$ENDIF}
{$ENDIF}
...
{$ENDIF}
Had never used the deprecated directive before. Tried to experiment a bit, used Lazarus to open a new trivia project where I declared a variable using identical syntax:and Lazarus raised exactly the same error again. Tried this on Delphi XE and once more got exactly the same error with the same message.
var Form1: TForm1; pap: Integer; deprecated;
Could not find some additional documentation either on the Delphi XE help subsystem or on the internet over deprecated.
Am left with the impression -please correct me if wrong- that this directive only works with procedures or methods but not with variables.
Many thanks for your kind help. Without you and GetMem, I simply couldn't have done it.
{$mode delphi}
var
GOffsetFromUTC: TDateTime =0 deprecated ;
begin
end.
compiles for me in 2.6.2,2.6.4,3.0.2,3.0.4 and trunk
Code: [Select]{$mode delphi}
compiles for me in 2.6.2,2.6.4,3.0.2,3.0.4 and trunk
var
GOffsetFromUTC: TDateTime =0 deprecated ;
begin
end.
Yes, that is the format that Indy uses in 2.6.2+.
Unlike with Delphi (which Indy supports all the way back to D5), Indy has little support for past FPC versions. The goal is to prefer to support only recent versions, since FPC is open-source and relatively easy for users to update at will.
Also have used:to send a string from the client app and
IdTCPClient1.IOHandler.WriteLn(Edit1.Text, IndyTextEncoding_OSDefault);to get the client string on the server app and this works happily with international characters.
LLine := AContext.Connection.IOHandler.ReadLn(IndyTextEncoding_OSDefault);
However replacing IndyTextEncoding_OSDefault with IndyTextEncoding_UTF8 on both apps wouldn’t work.
Seems unnecessary when both apps are running under the same OS.
Just for completion have tested again the Linux-Lazarus-Indy client app with the Windows-Delphi XE-Indy server app, this time using:at the windows server and it too worked as a breeze including international characters.
LLine := AContext.Connection.IOHandler.ReadLn(enUTF8);
But I still have issues each time I disconnect the client from the server. On Linux, both the server and the client app raise an exception.
But while on the server app I can handle this with the OnException event, I have failed to find a way to do the same client side.
I understand perfectly the reasons you have provided as to why this exception is raised and again I understand this exception is raised from deeply into the Indy code. Have tried a call to IdTCPClient1.CheckForGracefulDisconnect(False) before calling IdTCPClient1.Disconnect without success.
Have also tried IdTCPClient1.Disconnect(False) again with no success.
On this topic, one noticeable difference between the Linux-Lazarus-Indy-Server App and the Windows-Delphi XE-Indy-Server app has been that when closing the connection from the Linux-Lazarus-Indy-Client App the same exception is raised on the server side, yet it is not raised on the Lazarus client side.
Presume there must be some better way to close the connection from the client both graciously and without raising this exception but have failed to find it. How should I close the client-side connection without all this fuzz?
One last question please: I understand the tIdTCPServer has to be multi-threaded as multiple connections are supposed to be made against it from a number of clients. However is the tIdTCPClient multi threaded too?
Should I have to make thread-safe calls?
In regard to the on disconnect exception, ....
Looks like enUTF8 appears to be deprecated now, Indy prefers the IndyTextEncoding_*() functions instead, at least on Linux.
I understand the use of IndyTextEncoding_UTF8() should work for Linux and that it is the choice of preference, however for some reason it seems it doesn’t not work.
Looks the problem arises client side, as it is the client app that freezes while the server one appears as not getting anything.
Have managed to pass a Stream, had a lot of difficulties, until I read the example at https://github.com/tinydew4/indy-project-demos/tree/master/TCPIP%20Delphi%20%26%20Indy10%20Client%20Server%20Demo/4_sample%20Stream%20Exchange (https://github.com/tinydew4/indy-project-demos/tree/master/TCPIP%20Delphi%20%26%20Indy10%20Client%20Server%20Demo/4_sample%20Stream%20Exchange), and realize the use of buffered writes.
It is my understanding that to pass a stream I have to start by sending server the stream size first, then the actual stream so that the server will know the size of the stream to read.
In the example that saved my life, the author sends the size, then he ignites a buffered write by calling WriteBufferOpen that is before he sends the stream itself. Is this the correct way?
You have to try to handle the IdTCPServer1Disconnect(AContext: TIdContext) event to prevent disconnect except.
Not sure why. Again, can you please test it? You don't even need to make a TCP connection, simply use IndyTextEncoding_UTF8() by itself and encode/decode some strings with it. Make sure everything works correctly on Linux.Sorry Remy, have taken a look there http://packages.lazarus-ide.org (http://packages.lazarus-ide.org), where it claims to provide the latest Indy version 10.6.2.5457, which is exactly the one I currently use. By the way both the tIdTCPClient as well as tIdTCPServer report their corresponding versions to be 10.6.2.0 instead. Anyway whatever this version may be there is not much I have not tried so far, on this topic.
Sorry Remy, have taken a look there http://packages.lazarus-ide.org (http://packages.lazarus-ide.org), where it claims to provide the latest Indy version 10.6.2.5457, which is exactly the one I currently use. By the way both the tIdTCPClient as well as tIdTCPServer report their corresponding versions to be 10.6.2.0 instead.
Anyway whatever this version may be there is not much I have not tried so far, on this topic.
I presume perhaps you expect me to download the latest version from https://svn.atozed.com:444/svn/Indy10 (https://svn.atozed.com:444/svn/Indy10). Have no previous experience with SVN.
Have taken a look on synaptic -the debian source of heaven-, have found a number of SVN packages, do not know which one is the correct one to use. Not to mention that having tried to get on this page through http, I was asked for a user name and password that I could not provide.
This new package has a different directory structure from the previous one.
On adding package indylaz.lpk I got errors coming from unit IdSSLOpenSSL:as a result of which installation failed.
IdSSLOpenSSL.pas(3304,7) Error: Identifier not found "M" IdSSLOpenSSL.pas(3305,13) Error: ENDIF without IF(N)DEF IdSSLOpenSSL.pas(3306,7) Fatal: Syntax error, ";" expected but "identifier SSL_DEFAULT_CIPHER_LIST" found
Reversed back to the old version, but replaced unit IdGlobal.pas that contains the IndyTextEncoding_*() functions with that of the new version. Reinstalled patched old Indy version sans issues. Then tested:and failed.
at the client IdTCPClient1.IOHandler.WriteLn(Edit1.Text, IndyTextEncoding_UTF8()); at the server LLine := AContext.Connection.IOHandler.ReadLn(IndyTextEncoding_UTF8());
var
b: TIdBytes;
begin
b := IndyTextEncoding_UTF8.GetBytes(Edit1.Text);
// verify bytes are properly UTF-8 encoded...
Edit2.Text := IndyTextEncoding_UTF8.GetString(b);
end;
var
b: TIdBytes;
begin
b := ToBytes(Edit1.Text, IndyTextEncoding_UTF8);
// verify bytes are properly UTF-8 encoded...
Edit2.Text := BytesToString(b, IndyTextEncoding_UTF8);
end;
Much like with the previous version the client app freezes while apparently the server one does not get anything. Tested again, this time using NIL at the server only, still the same. Tested the opposite permutation with NIL on the client and IndyTextEncoding_UTF8() on the server, again came with nothing.
Can it be that the IndyTextEncoding_UTF8() function actually depends on one of the numerous include files to be found at the IdGlobal unit?
Downloaded version Indy10_5465.zip from https://indy.fulgan.com/ZIP/ again and had exactly the same installation issues I had on the previous attempt. You may find more information on this at my previous post. Anyway intend to give it another try as soon as I will be able to have a newer version installed.
The first example worked fine, was able to test the entire Greek alphabet without issues. The second one did not work at all. All EditBox Edit2 could get was an empty string.
Used the debugger on either procedures. On the first example variable b was populated after the execution of the statement:
b := IndyTextEncoding_UTF8.GetBytes(Edit1.Text);
On the second example variable b remained empty after a call to the statement:
b := ToBytes(Edit1.Text, IndyTextEncoding_UTF8);
The full execution path (in F7 steps) of the second example was:
- Unit IdGlobal procedure IndyTextEncoding_UTF8, obviously it was this resulting the empty string b
In both examples, executing procedure IndyTextEncoding_UTF8(), Indy finds GIdUTF8Encoding to be NIL before proceeding with the statement:
Result := GIdUTF8Encoding;
Hope it helps.
can you tell the ignorant me if I can use the tIdContext.Data property which is a tObject to store my local variables into the connection thread (eg the one to store the incoming stream and its size and perhaps any manipulative methods) or should I keep it off limits?
Quote from: scasparz on July 18, 2018, 12:53:45 amSorry Remy, am trying to do my best while am not a system developer.
Hope it helps.
Not really.
http://wiki.freepascal.org/Indy_with_LazarusAgain thanks for the information. Will use it next time. Took a look for a newer nightly at https://indy.fulgan.com/ZIP/ (https://indy.fulgan.com/ZIP/), seems it is now Forbidden, while I have been there multiple times. No other options for the moment other than keep using version 10.6.2.5457 unpatched.
And, was it populated *correctly*? Did you verify that the bytes were actually encoded using proper UTF-8 for Greek?Testing was done with the 'αβγδεζηθικλμνξοπρστυφχψω ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ άέήίόύώ ϊϋ ΐΰ' which is the entire Greek character set on the Edit1 editbox. All am trying to say is that what I got on Edit2 was a facsimile replica of what I had typed on Edit1. Plus Edit1.Text and Edit2.Text compare identical. No corruptions, no losses, everything came as it should. Looks example 1 works fine. If you want me to try something different with it please ask.
But, that doesn't tell me WHERE inside of Indy the data is getting lost exactly. I need you to step INSIDE of Indy's source code with the debugger, find out EXACTLY what happens at each step in the conversion process.I can absolutely understand you here, however F7 is the most detailed granularity with the debugger that I know. If there is a way to increase this further please advise me on how to do this. Meanwhile all I could do was to set a breakpoint at statement:
Took a look for a newer nightly at https://indy.fulgan.com/ZIP/ (https://indy.fulgan.com/ZIP/), seems it is now Forbidden, while I have been there multiple times.
No other options for the moment other than keep using version 10.6.2.5457 unpatched.
Testing was done with the 'αβγδεζηθικλμνξοπρστυφχψω ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ άέήίόύώ ϊϋ ΐΰ' which is the entire Greek character set on the Edit1 editbox.
CE B1 CE B2 CE B3 CE B4 CE B5 CE B6 CE B7 CE B8
CE B9 CE BA CE BB CE BC CE BD CE BE CE BF CF 80
CF 81 CF B3 CF 84 CF 85 CF 86 CF 87 CF 88 CF 89
20 CE 91 CE 92 CE 93 CE 94 CE 95 CE 96 CE 97 CE
98 CE 99 CE 9A CE 9B CE 9C CE 9D CE 9E CE 9F CE
A0 CE A1 CE A3 CE A4 CE A5 CE A6 CE A7 CE A8 CE
A9 20 CE AC CE AD CE AE CE AF CF 8C CF 8D CF 8E
20 CF 8A CF 8B 20 CE 90 CE B0
F7 is the most detailed granularity with the debugger that I know. If there is a way to increase this further please advise me on how to do this.
Ran example 2 with Latin chars, actually it contained the default editbox 'Edit1' text which I did not alter.
Looks this time the execution path was different though:
LEncoding := TIdUTF8Encoding.Create; constructor TIdUTF8Encoding.Create; TIdMBCSEncoding.Create; constructor TIdMBCSEncoding.Create(const CharSet: String); ... snip 8 TextIsSame() comparisons ... function PosInStrArray(const SearchStr: string; const Contents: array of string; const CaseSensitive: Boolean = True): Integer; exited with -1
function TIdUTF7Encoding.GetByteCount(const AChars: PIdWideChar; ACharCount: Integer): Integer;
from where I got a dialog box with message
<FILE NOT FOUND>
The file "iconv_open.c" was not found.
Do you want to locate it yourself?
Run it for the second time without changing the Edit1 contents. This time the execution path was different though. Instead of all that fuzz, there has been no call to theat the IndyTextEncoding_UTF8() function, however Edit2 contents remained correct.
LEncoding := TIdUTF8Encoding.Create;
Downloaded and installed latest nightly Indy10-10.6.2.5468 sans issues. Run the transliteration app again and got exactly the same results as before. The quick answer is that example 1 passes with flying colours while example 2 fails.
Do you think I had to compile Indy twice as with older versions?
To start with Lazarus maps String to AnsiString through the omnipresent default directive {$H+} at least on Linux-64.
For some reason GDB would not take me to the ToBytes function using F7 during the runs of the previous days.
This time I set an explicit breakpoint and was the first time I saw the execution of this code. Suspect maybe this is where the problem lies, for IndyTextEncoding_UTF8() seems to be working fine with the syntax of the example1.
This time I set an explicit breakpoint and was the first time I saw the execution of this code.
{$IFDEF STRING_IS_ANSI} LBytes := nil; // keep the compiler happy // (0) {$ENDIF}
LLength := IndyLength(AValue, ALength, AIndex); // (1), LLength becomes 4
EnsureEncoding(ADestEncoding); // (3) ADestEncoding = IUNKNOWN, GDB won't let me F7 this
EnsureEncoding(ASrcEncoding, encOSDefault); // (4) ASrcEncoding = IUNKNOWN
LBytes := RawToBytes(AValue[AIndex], LLength); // (5) LBytes becomes (206,177,206,178)
CheckByteEncoding(LBytes, ASrcEncoding, ADestEncoding); // (6) LBytes becomes ()
Have F7ed CheckByteEncoding as well.[/code]
procedure CheckByteEncoding(var VBytes: TIdBytes; ASrcEncoding, ADestEncoding: IIdTextEncoding); begin if ASrcEncoding <> ADestEncoding then begin // according to the GDB both ASrcEncoding and ADestEncoding are valued IUNKNOWN VBytes := ADestEncoding.GetBytes(ASrcEncoding.GetChars(VBytes)); // (8) this statement is executed, should it? end; end;
Both ASrcEncoding as well as ADestEncoding are of the IIdTextEncoding type, which I understand is an interface.
Have no clues on how do interfaces compare
Would expect statement #8 to not be executed.
Cannot F7 statement #8 of course.
- set the IdGlobal.GIdDefaultTextEncoding variable to encUTF8 instead of its default value of encASCII.Added this on app main, it did not work.
Again, did you recompile Indy with debug info enabled?Do not have a clue here. GDB would let me F7 some parts but may keep a few others out of reach. Haven’t changed anything on Indy, would expect there must be some centralized management on that, probably at some include file or unit. Have taken a look at Lazpack.lpk, have found nothing to be there. Have noticed the existence of a number of DEBUG_STRING_MISMATCH on IdGlobal.pas, but would expect them to be unrelated. Perhaps then you could enlighten me on where to look for.
Quote- set the IdGlobal.GIdDefaultTextEncoding variable to encUTF8 instead of its default value of encASCII.Added this on app main, it did not work.
Have noticed the existence of a number of DEBUG_STRING_MISMATCH on IdGlobal.pas, but would expect them to be unrelated.
i've been battling since june to get lazarus working reliably on ubuntu 16.04 then 18.04.