#1 Re: mORMot 2 » Performance of Mormot Collections vs. Spring v2 Collections » 2023-11-15 06:35:29

Hello,

Interesting.

I added another generic collections lib which on

https://github.com/d-mozulyov/Rapid.Generics


program SpringVsMormotCollections;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Diagnostics,
  mormot.core.collections,
  Spring,
  Spring.Collections
  , Rapid.Generics
  ;

{ ----------------------------------------------------------------------- }

type

  TBenchmarks = class
   private
    function CreateTestListString(ACount: Integer; const APrefix: String): TArray<String>;
    procedure RunBenchmark(const AProc: TProc; ABenchmarkRounds: Integer);
    procedure ListBenchmark;
    procedure DictBenchmark;
   public
    procedure Run;
  end;

{ ======================================================================= }
{ TBenchmarks                                                             }
{ ======================================================================= }

function TBenchmarks.CreateTestListString(ACount: Integer; const APrefix: String): TArray<String>;
begin
  SetLength(Result, ACount);
  for var Loop:=0 to ACount-1
    do Result[Loop]:=APrefix+' #'+IntToStr(Loop+1);
end;

{ ----------------------------------------------------------------------- }

procedure TBenchmarks.DictBenchmark;
const
  BenchRounds = 100;
begin
  var TestKeys:=CreateTestListString(100000,'Key');
  var TestValues:=CreateTestListString(100000,'Value');

  var MormotDict:=Collections.NewKeyValue<String,String>;
  var SpringDict:=TCollections.CreateDictionary<String,String>;
  var RapidDict:=Rapid.Generics.TRapidDictionary<String, String>.Create;

  Writeln(Format('Populate MormotDict with %d items...',[Length(TestKeys)]));
  RunBenchmark(
    procedure
    begin
      MormotDict.Clear;
      for var Loop:=0 to Length(TestKeys)-1
        do MormotDict.Add(TestKeys[Loop],TestValues[Loop]);
    end,BenchRounds);

  Writeln(Format('Populate SpringDict with %d items...',[Length(TestKeys)]));
  RunBenchmark(
    procedure
    begin
      SpringDict.Clear;
      for var Loop:=0 to Length(TestKeys)-1
        do SpringDict.Add(TestKeys[Loop],TestValues[Loop]);
    end,BenchRounds);

  Writeln(Format('Populate RapidDict with %d items...',[Length(TestKeys)]));
  RunBenchmark(
    procedure
    begin
      RapidDict.Clear;
      for var Loop:=0 to Length(TestKeys)-1
        do RapidDict.Add(TestKeys[Loop],TestValues[Loop]);
    end,BenchRounds);

  Writeln(Format('---------------------------------... %d',[Length(TestKeys)]));

  Writeln('Compare MormotDict with SpringDict...');
  RunBenchmark(
    procedure
    var
      CurKey        : String;
      CurMormotValue: String;
      CurSpringValue: String;
    begin
      for var Loop:=0 to Length(TestKeys)-1 do
      begin
        CurKey:=TestKeys[Loop];
        if not
          (
            MormotDict.TryGetValue(CurKey,CurMormotValue) and
            SpringDict.TryGetValue(CurKey,CurSpringValue) and
            (CurMormotValue=CurSpringValue)
          )
          then raise Exception.Create('Different content!');
      end;
    end,BenchRounds);

  Writeln('Compare MormotDict with RapidDict...');
  RunBenchmark(
    procedure
    var
      CurKey        : String;
      CurMormotValue: String;
      CurSpringValue: String;
    begin
      for var Loop:=0 to Length(TestKeys)-1 do
      begin
        CurKey:=TestKeys[Loop];
        if not
          (
            MormotDict.TryGetValue(CurKey,CurMormotValue) and
            RapidDict.TryGetValue(CurKey,CurSpringValue) and
            (CurMormotValue=CurSpringValue)
          )
          then raise Exception.Create('Different content!');
      end;
    end,BenchRounds);

  Writeln('Compare SpringDict with RapidDict...');
  RunBenchmark(
    procedure
    var
      CurKey        : String;
      CurMormotValue: String;
      CurSpringValue: String;
    begin
      for var Loop:=0 to Length(TestKeys)-1 do
      begin
        CurKey:=TestKeys[Loop];
        if not
          (
            RapidDict.TryGetValue(CurKey,CurSpringValue) and
            SpringDict.TryGetValue(CurKey,CurMormotValue) and
            (CurMormotValue=CurSpringValue)
          )
          then raise Exception.Create('Different content!');
      end;
    end,BenchRounds);

  Writeln(Format('---------------------------------... %d',[Length(TestKeys)]));

  Writeln('Iterate MormotDict by key (TryGetValue)...');
  RunBenchmark(
    procedure
    var
      CurKey  : String;
      CurValue: String;
    begin
      for var Loop:=0 to Length(TestKeys)-1 do
      begin
        CurKey:=TestKeys[Loop];
        if not MormotDict.TryGetValue(CurKey,CurValue)
          then raise Exception.Create('Something is wrong!');
      end;
    end,BenchRounds);

  Writeln('Iterate SpringDict by key (TryGetValue)...');
  RunBenchmark(
    procedure
    var
      CurKey  : String;
      CurValue: String;
    begin
      for var Loop:=0 to Length(TestKeys)-1 do
      begin
        CurKey:=TestKeys[Loop];
        if not SpringDict.TryGetValue(CurKey,CurValue)
          then raise Exception.Create('Something is wrong!');
      end;
    end,BenchRounds);

  Writeln('Iterate RapidDict by key (TryGetValue)...');
  RunBenchmark(
    procedure
    var
      CurKey  : String;
      CurValue: String;
    begin
      for var Loop:=0 to Length(TestKeys)-1 do
      begin
        CurKey:=TestKeys[Loop];
        if not RapidDict.TryGetValue(CurKey,CurValue)
          then raise Exception.Create('Something is wrong!');
      end;
    end,BenchRounds);

  Writeln(Format('---------------------------------... %d',[Length(TestKeys)]));

  Writeln('Iterate (for..in) MormotDict ...');
  RunBenchmark(
    procedure
    var
      CurKey  : String;
      CurValue: String;
    begin
      for var Entry in MormotDict do
      begin
        CurKey:=Entry.Key;
        CurValue:=Entry.Value;
      end;
    end,BenchRounds);

  Writeln('Iterate (for..in) SpringDict ...');
  RunBenchmark(
    procedure
    var
      CurKey  : String;
      CurValue: String;
    begin
      for var Entry in SpringDict do
      begin
        CurKey:=Entry.Key;
        CurValue:=Entry.Value;
      end;
    end,BenchRounds);

  Writeln('Iterate (for..in) RapidDict ...');
  RunBenchmark(
    procedure
    var
      CurKey  : String;
      CurValue: String;
    begin
      for var Entry in RapidDict do
      begin
        CurKey:=Entry.Key;
        CurValue:=Entry.Value;
      end;
    end,BenchRounds);

  Writeln(Format('---------------------------------... %d',[Length(TestKeys)]));
end;

{ ----------------------------------------------------------------------- }

procedure TBenchmarks.ListBenchmark;
const
  BenchRounds = 100;
begin
  var TestData:=CreateTestListString(100000,'Value');
  var MormotList:=Collections.NewList<String>;
  var SpringList:=TCollections.CreateList<String>;
  var RapidList:=Rapid.Generics.TList<string>.create;

  Writeln(Format('Populate MormotList with %d items...',[Length(TestData)]));
  RunBenchmark(
    procedure
    begin
      MormotList.Clear;
      for var Entry in TestData do
      begin
        MormotList.Add(Entry);
      end;
    end,BenchRounds);

  Writeln(Format('Populate SpringList with %d items...',[Length(TestData)]));
  RunBenchmark(
    procedure
    begin
      SpringList.Clear;
      for var Entry in TestData do
      begin
        SpringList.Add(Entry);
      end;
    end,BenchRounds);

  Writeln(Format('Populate RapidList with %d items...',[Length(TestData)]));
  RunBenchmark(
    procedure
    begin
      RapidList.Clear;
      for var Entry in TestData do
      begin
        RapidList.Add(Entry);
      end;
    end,BenchRounds);

  Writeln(Format('---------------------------------... %d',[Length(TestData)]));

  Writeln('Compare MormotList with SpringList...');
  RunBenchmark(
    procedure
    begin
      for var Loop:=0 to SpringList.Count-1 do
      begin
        if MormotList[Loop]<>SpringList[Loop]
          then raise Exception.Create('Different content!');
      end;
    end,BenchRounds);

  Writeln('Compare MormotList with RapidList...');
  RunBenchmark(
    procedure
    begin
      for var Loop:=0 to MormotList.Count-1 do
      begin
        if MormotList[Loop]<>RapidList[Loop]
          then raise Exception.Create('Different content!');
      end;
    end,BenchRounds);

  Writeln('Compare SpringList with RapidList...');
  RunBenchmark(
    procedure
    begin
      for var Loop:=0 to SpringList.Count-1 do
      begin
        if SpringList[Loop]<>RapidList[Loop]
          then raise Exception.Create('Different content!');
      end;
    end,BenchRounds);

  Writeln(Format('---------------------------------... %d',[Length(TestData)]));

  Writeln('Iterate (for..in) through MormotList...');
  RunBenchmark(
    procedure
    begin
      var LastEntry: String;
      for var Entry in MormotList do
      begin
        LastEntry:=Entry;
      end;
    end,BenchRounds);

  Writeln('Iterate (for..in) through SpringList...');
  RunBenchmark(
    procedure
    begin
      var LastEntry: String;
      for var Entry in SpringList do
      begin
        LastEntry:=Entry;
      end;
    end,BenchRounds);

  Writeln('Iterate (for..in) through RapidList...');
  RunBenchmark(
    procedure
    begin
      var LastEntry: String;
      for var Entry in RapidList do
      begin
        LastEntry:=Entry;
      end;
    end,BenchRounds);

  Writeln(Format('---------------------------------... %d',[Length(TestData)]));

  Writeln('Iterate (for..to) through MormotList...');
  RunBenchmark(
    procedure
    begin
      var LastEntry: String;
      for var Loop:=0 to MormotList.Count-1 do
      begin
        LastEntry:=MormotList[Loop];
      end;
    end,BenchRounds);

  Writeln('Iterate (for..to) through SpringList...');
  RunBenchmark(
    procedure
    begin
      var LastEntry: String;
      for var Loop:=0 to SpringList.Count-1 do
      begin
        LastEntry:=SpringList[Loop];
      end;
    end,BenchRounds);

  Writeln('Iterate (for..to) through RapidList...');
  RunBenchmark(
    procedure
    begin
      var LastEntry: String;
      for var Loop:=0 to RapidList.Count-1 do
      begin
        LastEntry:=RapidList[Loop];
      end;
    end,BenchRounds);
end;

{ ----------------------------------------------------------------------- }

procedure TBenchmarks.RunBenchmark(const AProc: TProc; ABenchmarkRounds: Integer);
begin
  var Stopper:=TStopwatch.StartNew;
  for var Loop:=1 to ABenchmarkRounds do
  begin
    AProc;
  end;
  Stopper.Stop;
  Writeln(Format('- (%d runs in %d msec.)',[ABenchmarkRounds,Stopper.ElapsedMilliseconds]));
  Writeln;
end;

{ ----------------------------------------------------------------------- }

procedure TBenchmarks.Run;
begin
  Writeln('---ListBenchmark---');
  ListBenchmark;

  Writeln('---DictBenchmark---');
  Writeln('---DictBenchmark---');
  Writeln('---DictBenchmark---');
  DictBenchmark;
end;

{ ======================================================================= }

begin
  try
    var Benchmarks:=TBenchmarks.Create;
    try
      Benchmarks.Run;
    finally
      Benchmarks.Free;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

  Writeln('Done. Press Enter for exit.');
  Readln;
end.

And here is a result.

---ListBenchmark---
Populate MormotList with 100000 items...
- (100 runs in 275 msec.)

Populate SpringList with 100000 items...
- (100 runs in 245 msec.)

Populate RapidList with 100000 items...
- (100 runs in 241 msec.)

---------------------------------... 100000
Compare MormotList with SpringList...
- (100 runs in 214 msec.)

Compare MormotList with RapidList...
- (100 runs in 287 msec.)

Compare SpringList with RapidList...
- (100 runs in 285 msec.)

---------------------------------... 100000
Iterate (for..in) through MormotList...
- (100 runs in 353 msec.)

Iterate (for..in) through SpringList...
- (100 runs in 203 msec.)

Iterate (for..in) through RapidList...
- (100 runs in 285 msec.)

---------------------------------... 100000
Iterate (for..to) through MormotList...
- (100 runs in 102 msec.)

Iterate (for..to) through SpringList...
- (100 runs in 109 msec.)

Iterate (for..to) through RapidList...
- (100 runs in 236 msec.)

---DictBenchmark---
---DictBenchmark---
---DictBenchmark---
Populate MormotDict with 100000 items...
- (100 runs in 1216 msec.)

Populate SpringDict with 100000 items...
- (100 runs in 962 msec.)

Populate RapidDict with 100000 items...
- (100 runs in 573 msec.)

---------------------------------... 100000
Compare MormotDict with SpringDict...
- (100 runs in 848 msec.)

Compare MormotDict with RapidDict...
- (100 runs in 826 msec.)

Compare SpringDict with RapidDict...
- (100 runs in 483 msec.)

---------------------------------... 100000
Iterate MormotDict by key (TryGetValue)...
- (100 runs in 578 msec.)

Iterate SpringDict by key (TryGetValue)...
- (100 runs in 286 msec.)

Iterate RapidDict by key (TryGetValue)...
- (100 runs in 297 msec.)

---------------------------------... 100000
Iterate (for..in) MormotDict ...
- (100 runs in 662 msec.)

Iterate (for..in) SpringDict ...
- (100 runs in 402 msec.)

Iterate (for..in) RapidDict ...
- (100 runs in 611 msec.)

---------------------------------... 100000
Done. Press Enter for exit.

#2 Re: mORMot 2 » TDynArrayHashed custom sortcompare function with a sort rule pass in? » 2023-11-07 08:51:17

Hello Ab,

Thanks for you note.

Currently I use TObjectDictionary, and I would like to try TDynArrayHashed  or TSynDictionary for better performance and if could save some memory.

As you said, that the TDynArrayHashed  will not sort when add a new Item to the array?  So that it will not re-sort when update the record?  When a record is changed and need re-sort, how about use the SortRange for a better performance?

In my case the array will init only once then sort or sort full array when the user change the sort field he selected, and the items will update frequently so it need re-sort when every time a record filed get changed.
Would you advice to try the TDynArrayHashed  or TSynDictionary  or the plain TDynArray  or just stay with TObjectDictionary?


Thank you

#3 Re: mORMot 2 » TDynArrayHashed custom sortcompare function with a sort rule pass in? » 2023-11-07 06:53:43

Just found that the TOnDynArraySortCompare is what I need.

Thanks

#4 mORMot 2 » TDynArrayHashed custom sortcompare function with a sort rule pass in? » 2023-11-07 06:12:20

wqmeng
Replies: 4

Hello,

I am try to use the TDynArrayHashed to store a long list of records. And would like to sort the Array base on the record fields.  And the sort rule will base on field1, or field2 which is selected by the user.

R1 = record
  f1: integer;
  f2: string;
  f3: double
end

So that how to pass the sort rule to the compare function?

  TDynArraySortCompare = function(const A, B): integer;

  /// event oriented version of TDynArraySortCompare
  TOnDynArraySortCompare = function(const A, B): integer of object;


When I try to add the custom_record_comapre function to the TDynArrayHashed.Init function,  The custom_record_comapre  function can not be a Object function, so it can not access the sort_rule owned by the Object.

I have to define a global var of the Object or the sort_rule and use it in the custom_record_comapre  function?  But I have not only one Object different of them may sort by different record filed.  Let say Object1 sort rule is record field1,  Object2 sort rule is record field2.

Thank you.

#5 Re: mORMot 2 » DynArrayLoadJson can not process the JSON with "a", "A" names data? » 2023-10-26 04:52:14

Hello Thomas and ab,

Thank you for all your great works.

Since we added ToDouble function, why not also add a ToCurrency function too?  They are almost the same.

And another matter which is not a must be feature, we have found that when we would like to skip some field, in this case if we only want 'A' and skip 'a', and set recValues = array[0..1] of TValuePUtf8Char;

pmvContext.ParseObject(['c', 'A'], @recValues)

We will get the 'c', 'a' values, not 'c', 'A'.

I also tried to change the props name in the rtti with

Rtti.ByTypeInfo[TypeInfo(TTestRec)].Props.NameChanges(['a2'], ['A']);

It seems that the above changes will not work.
I mean the parser will not care the Props Name's Letter case. If the Name is case sensitive, then the problems above should all get resolved.

Thank you very much.

#6 Re: mORMot 2 » DynArrayLoadJson can not process the JSON with "a", "A" names data? » 2023-10-22 08:59:59

@larand54

Sorry, I cut a small part from a long list of fields and forget to delete the COMMA at the end.

@Thomas

And do you know if it is possible to match a nested record such as by the DynArrayLoadJson in this case?

type
PTR1 = ^TR1;
TR1 = packed record
  a1: double;
  a2: double;
end;

TTestRec = packed record
  c: double;
  R1: PTR1;
end;

OR 

TTestRec = record
  c: double;
  R1: TR1;
end;

TTestRecArray = array of TTestRec;

const
  JSON = '[{"c": "28403.81000000","a": "28420.61000000","A": "0.00351000"},{"c": "0.13690000","a": "0.13930000","A": "408.00000000"}]';
var
  recs: TTestRecArray;

As you see that we split the JSON text to be a nested record, and would like to DynArrayLoadJson the JSON directly to the recs array.

Thank you

#8 mORMot 2 » DynArrayLoadJson can not process the JSON with "a", "A" names data? » 2023-10-21 09:47:22

wqmeng
Replies: 8

Hello ab,  nice again.

I read a Json from a web service which return with a JSON array such as

[
   {
      "c": "28403.81000000",
      "a": "28420.61000000",
      "A": "0.00351000",
   },
   {
      "c": "0.13690000",
      "a": "0.13930000",
      "A": "408.00000000",
   }
]

When try DynArrayLoadJson to parse the Json text, it will not process the "a" and "A" name of data. Report a error

First chance exception at $769390E2. Exception class ERttiException with message 'Duplicated A property name'.

So that in this case there is not possible to use DynArrayLoadJson function? Will you consider to handle this?

Tough the data titile "a" and "A" is Duplicated consider by pascal language, but our purpose is to parse the data to a pre-defined record, even the name is Duplicated in the Json text, that will not matter.

Thank you.

#9 Re: mORMot 1 » websockets client base on mORMot work with a common websocket server? » 2017-10-02 17:17:50

Hello AB,

1, The wss is from the Chrome capture data,  and My first aim is to get the ws:// without TLS to work.

2, I checked out the Project31SimpleEchoServer.dpr, It is the server part,  You see my code posted here which try to get the client part to work, but not work out yet.  As you focus on the interface implement, so that if I want to get a client to connect a Node.js server, I will need to work from the client standard webSockets protocol?


Thank you very much.

#10 Re: mORMot 1 » websockets client base on mORMot work with a common websocket server? » 2017-10-02 16:26:48

Hello AB,

Are you interesting this and can help with this?  Websockets is popular now and mostly the wesockets servers are node.js or other python servers,  so that we can use client part in Delphi to deal with them.

And big thank you for sharing the nice framework.  Will try to learn more of it.

#11 Re: mORMot 1 » websockets client base on mORMot work with a common websocket server? » 2017-09-29 17:08:28

I added some new code try to send a frame to the server, but when I trace the code and get some access violation errors when ProcessMask ,  not sure why.

        protocol := TWebSocketProtocolChat.Create('meow', '');
        process := TMyWebSocketProcessClient.Create(Client.WebSockets, protocol, 'mORMotWebsocketClientProcess');

        //Client.WebSockets.WebSockets:= process;
        //process := Client.WebSockets.WebSockets;
        frame.opcode := TWebSocketFrameOpCode.focText;
        frame.content := [];
        frame.payload := 'hello, test chat!';


        if process.SendFrame(frame) then begin
          memo1.lines.add('send frame success');
        end;

The problem code is

PCardinalArray(data)^[i] := PCardinalArray(data)^[i] xor mask;

And SendFrame fail.

#12 Re: mORMot 1 » websockets client base on mORMot work with a common websocket server? » 2017-09-29 15:48:47

General
Request URL:wss://echo.websocket.org/?encoding=text
Request Method:GET
Status Code:101 Web Socket Protocol Handshake

Response Headers
view source
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:x-websocket-protocol
Access-Control-Allow-Headers:x-websocket-version
Access-Control-Allow-Headers:x-websocket-extensions
Access-Control-Allow-Headers:authorization
Access-Control-Allow-Headers:content-type
Access-Control-Allow-Origin:https://www.websocket.org
Connection:Upgrade
Date:Fri, 29 Sep 2017 15:49:54 GMT
Sec-WebSocket-Accept:N+kpt4PQBw7C/MeTZPzLHON+AeA=
Server:Kaazing Gateway
Upgrade:websocket

Request Headers
view source
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.8
Cache-Control:no-cache
Connection:Upgrade
Cookie:__zlcmid=ikgmcydUmlJ7z4; _ga=GA1.2.1394516097.1506699313; _gid=GA1.2.814511308.1506699313; _gat=1
Host:echo.websocket.org
Origin:https://www.websocket.org
Pragma:no-cache
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits
Sec-WebSocket-Key:ML8U6aK3xJQQTgdKUaHjlQ==
Sec-WebSocket-Version:13
Upgrade:websocket
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
Query String Parameters
view source
view URL encoded
encoding:text

#13 Re: mORMot 1 » websockets client base on mORMot work with a common websocket server? » 2017-09-29 15:46:16

After I watch the chrome connection to echo.websocket.org,  from the data which show in the developer tools,

Now the echo.websocket.org server is waiting my client to send some headers to complete the handshake ?

#14 Re: mORMot 1 » websockets client base on mORMot work with a common websocket server? » 2017-09-29 15:21:07

And I dump the headers to memo1. 

        for I := Low(Client.WebSockets.Headers) to High(Client.WebSockets.Headers) do begin
          memo1.Lines.Add(Client.WebSockets.Headers[ I]);
        end;

From the headers,  it shows

Connection: Upgrade
Date: Fri, 29 Sep 2017 15:19:00 GMT
Sec-WebSocket-Accept: PnZv2+arapwxuaf6vrXbBQYwBJc=
Server: Kaazing Gateway
Upgrade: websocket

So, the client should be upgrade to be a websockets connection with  echo.websocket.org .


Then I do know how to send message and receive the data from the server.

#15 Re: mORMot 1 » websockets client base on mORMot work with a common websocket server? » 2017-09-29 15:16:58

After change the

Client.WebSocketsUpgrade('', true) 
to
Client.WebSockets.WebSocketsUpgrade('/?encoding=text', '')

Then, It seems that I can upgrade the client to a websockets connection.  But I still get the error string 'Invalid HTTP Upgrade Header' ;


Here is I get result in memo1.

Invalid HTTP Upgrade Header
echo.websocket.org
SockConnected true

Connection: Upgrade
Date: Fri, 29 Sep 2017 15:19:00 GMT
Sec-WebSocket-Accept: PnZv2+arapwxuaf6vrXbBQYwBJc=
Server: Kaazing Gateway
Upgrade: websocket

#16 Re: mORMot 1 » websockets client base on mORMot work with a common websocket server? » 2017-09-29 14:58:51

Hi, after review the code of Samples\31 - Project31ChatServer and Project31ChatClient,  Do they implement the websockets standard?   I think that they are not common websockets applications.

#17 Re: mORMot 1 » websockets client base on mORMot work with a common websocket server? » 2017-09-29 13:40:19

From the memo1,  I get some result shows the upgrade failure,

Invalid HTTP Upgrade Header
echo.websocket.org
SockConnected true
<html><head></head><body><h1>404 WebSocket Upgrade Failure</h1></body></html>HTTP/1.1 501 Not Implemented

#18 mORMot 1 » websockets client base on mORMot work with a common websocket server? » 2017-09-29 13:35:24

wqmeng
Replies: 10

Hi,

I'm new of mORMot, now I try to build a application which receive the data from a web servers which use websockets as their method to delivery the data real time. Then I find that mORMot has some units which do many websockets works,  so I would like to build my application base on the units of mORMot,  Then after I looked all the demo of Samples 31, I see that all the websockets client implication base on the Interface with the mORMot websockets server.  So I want to know if the units that I can build on them may create a websockets client application which can talk with the other websockets servers already built by others languages NOT base on the windows Interface technology?

I have tried some code and do not know how to do that,  Can you help to get my test to work with the websockets site such as echo.websocket.org ?  The demo server is https://www.websocket.org/echo.html .

Here I have some code, just get some errors with upgrade to websockets failed, What I need to add some raw header strings to get it to work?

procedure TForm2.Button6Click(Sender: TObject);
var Client: TSQLHttpClientWebsockets;
    workName: string;
    cmd, msg: SockString;
begin
  Client := TSQLHttpClientWebsockets.Create('echo.websocket.org','80',TSQLModel.Create([]));
  try
    Client.Model.Owner := Client;
    Client.WebSockets.Settings.SetFullLog;
//    Client.WebSocketsUpgrade(PROJECT31_TRANSMISSION_KEY);
    memo1.Lines.Add( Client.WebSocketsUpgrade('', true) );
    try
        memo1.Lines.Add(Client.WebSockets.Server);
        if Client.WebSockets.SockConnected then
          memo1.Lines.Add('SockConnected true');

        Client.WebSockets.SockSend('Hello, websocket.org');
        Client.WebSockets.SockSendFlush;

        Client.WebSockets.SockRecvLn(msg);
        memo1.Lines.Add(msg);
    finally
      //callback := nil;
      //Service := nil; // release the service local instance BEFORE Client.Free
    end;
  finally
    Client.Free;
  end;
end;

Thank you.

Board footer

Powered by FluxBB