#1 2024-04-25 17:20:43

Paul117
Member
Registered: 2024-04-25
Posts: 3

Can't find info on using TWebSocketAsyncServer for basic echo server

I first declare my present deep frustrations are overshadowed by astonishment at Arnaud's impressive Delphi mastery and abundant open source generosity. Merci beaucoup, Arnaud.

TL;DR: Just trying to get a basic Websockets client/server Delphi application working using the new high-performance TWebSocketAsyncServer mentioned here: https://blog.synopse.info/?post/2022/05 … n-mORMot-2

My frustration is there's no explanatory documentation available or general getting started guidance on TWebSocketAsyncServer (as there are abundant resources on other, older components) and it seems there is a presumption of expertise in older mORMot 1 concepts/source to know what to do for even the most basic usage. The Github has two unrelated examples: http-server-raw works perfectly for getting a request callback and sending data to client/browser, but I need this for Websockets.

The one Websocket example there is ("rest-websockets") doesn't use the new Asynch objects, and has this confusing/weird "interface" and "service" and "REST" stuff I don't need or want to spend the time trying to understand.
I just want an event handler on WS message from client and API to write to connected client(s) for low-level binary packet streaming server (Win32 x64) over port 80 to/from Delphi Win32 x64 clients. I don't need, want, or even understand any of the high-level "business logic" wasteful object/REST/SOA/ORM stuff. This screams of dynamic heap allocations, added complexity, and higher overhead not needed for my application.

Problems:

1. "OnRequest" never gets called below even when WS client is connected and then sends a message:

procedure TMyServer.WebsocketOnConnect(Sender: TWebSocketAsyncConnection);
begin
  WriteLn('Connected: '+Sender.RemoteIP);
end;

procedure TMyServer.WebsocketOnDisconnect(Sender: TWebSocketAsyncConnection);
begin
  WriteLn('Disconnected: '+Sender.RemoteIP);
end;

function TMyServer.WebsocketOnRequest(Ctxt: THttpServerRequestAbstract): Cardinal;
begin//Never gets called
  WriteLn('Request: '+Ctxt.RemoteIP);
  Ctxt.OutContent := 'Test: '+Ctxt.InHeaders;
  Ctxt.OutContentType := TEXT_CONTENT_TYPE;
end;

constructor TMyServer.Create;
begin
  inherited Create;
  WS := TWebSocketAsyncServer.Create('80', nil, nil, '', SystemInfo.dwNumberOfProcessors + 1, 20000);

  //I wasted aimless hours of my client getting "400 Bad Request" until somehow finding out I needed this
  //What mORMot documentation in existence did I fail to read?
  WS.WebSocketProtocols.AddOnce(TWebSocketProtocolBinary.Create(''));

  WS.OnWebSocketConnect := WebsocketOnConnect;
  WS.OnWebSocketDisconnect := WebsocketOnDisconnect;
  WS.OnRequest := WebsocketOnRequest;
  WS.WaitStarted;
end;

2. No attempts to write data from server to client (beyond the initial upgrade response to websockets) have resulted in Wireshark localhost http filter showing any traffic. Client receives no data. I don't have details or code on this second task here because I don't even know how to go about learning what mORMot API calls to use to send data. I've only attempted a shotgun approach of perusing the source code and seeing what looks like might work, such as calling Send on WS.Socket. It gives the impression of necessary guesswork, using low level functions not intended for the application but internally used by mORMot, and reassures the developer they have absolutely no clue what they are doing or how to actually use TWebSocketAsyncServer to make a basic echo server like https://echo.websocket.org/ with mORMot.


What I have done:

0. I have ensured that my code snippet above is not of excessive length in violation of Forum Rule #7.
1. I have confirmed that none of the examples depict a base websockets echo server using this new mORMot API.
2. I have read this documentation page which does not explain how to send data to clients or get a callback when receiving messages: https://synopse.info/files/doc/api/morm … SYNCSERVER
3. I have tried randomly messing around with no guidance with WS.Sock.SockSend, WS.Async.Server.SockSend('test data'), TWebSocketAsyncConnection(Sender).Send() in the OnConnect callback, etc.
4. I have examined and read the source unit mormot.net.ws.sync and mormot.net.sync, encountering very frustrating snippets of hope that lead to disappointment and confusion, such as:

// - ProcessRead/ProcessWrite methods are to be run for actual communication:
  // either you call those methods from multiple threads, or you run them in
  // loop from a single thread, then define a TSynThreadPool for running any
  // blocking process (e.g. computing requests answers) from OnRead callbacks
  TPollAsyncSockets = class
...

Where is TPollAsyncSockets in my variable "WS" above of type TWebSocketAsyncServer? The comment says "use ProcessWrite", but where do I find documentation telling me how to use this? WS.Clients seemed hopeful, but does not give me callbacks or write/read functions. So, I have no idea how to actually make a basic sample WS echo server that sends a test string/binary packet to client and vice-versa.

Thank you in advance for any help. This is clearly such a powerful and efficient Websockets server solution if I can only figure out how to use it. Please point-out the cause of my disorientation in however forceful of a manner needed, but I do believe my post reflects what a 15-year professional Delphi developer would come up with after about 7 hours of effort leading only to getting the connection to accept (first 3 hours had no idea you needed to send "Sec-WebSocket-Protocol: synopsebinary" in client and add WS.WebSocketProtocols.AddOnce(TWebSocketProtocolBinary.Create('')); - that was very frustrating)

Offline

#2 2024-04-25 17:42:12

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,242
Website

Re: Can't find info on using TWebSocketAsyncServer for basic echo server

Thanks a lot for your interest.

You need to write your own protocol.

Try to start from https://github.com/synopse/mORMot/blob/ … Server.dpr
changing the units to mORMot 2 names, and TWebSocketAsyncServer instead of TWebSocketServer.

But it is more complex than using the interface-based services definition.
And defining your interfaces makes writing the client direct to use, with regular pascal code, without the need of writing low-level code at protocol level.
You will gain much more by taking a little time to look at the interface-based services instead of reinventing the wheel with your own protocol.

Offline

#3 2024-04-26 00:19:22

Paul117
Member
Registered: 2024-04-25
Posts: 3

Re: Can't find info on using TWebSocketAsyncServer for basic echo server

Thank you Arnaud. This is an immediate half-victory to know mORMot 1 has exactly what I am looking for (this example you indicated). I can rely upon mORMot 1 in the worst case I fail to accomplish your advice of substituting to mORMot 2. However, since this server will have to service thousands of simultaneous connections (though less than 10000) I think it's desirable to have the better performance, scalable asynch improved server in mORMot 2. I will report back if I encounter any blockages.

Last edited by Paul117 (2024-04-26 07:16:37)

Offline

#4 2024-04-26 06:58:22

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,242
Website

Re: Can't find info on using TWebSocketAsyncServer for basic echo server

I did not write to use mORMOt 1, I wrote to adapt the mORMOt 1 sample to use the mORMot 2 units.
mORMot 2 has everything you need for your task.

Offline

#5 2024-04-26 07:16:15

Paul117
Member
Registered: 2024-04-25
Posts: 3

Re: Can't find info on using TWebSocketAsyncServer for basic echo server

ab wrote:

I did not write to use mORMOt 1, I wrote to adapt the mORMOt 1 sample to use the mORMot 2 units.
mORMot 2 has everything you need for your task.

Of course; I did understand this guidance. Unfortunately though, I now find myself happily using the working mORMot 1 Websockets example, thanks to your guidance thereto (for the purpose of then attempting the refactoring to mORMot 2). I'm now able to amend the read/write logic to my application binary messaging infrastructure, so I'm struggling to justify spending time attempting the code adaptation to mORMot 2. At least at this stage of my project, where I'd rather focus on the messaging logic itself.

Would you say the amount of performance I am leaving on the table until I attempt to adapt to mORMot 2 could be subjectively significant? I know I can eventually put in the effort to use your newest and most optimized work, and seeing as though my application will never exceed a few thousand simultaneous websockets reading/writing small packets of less than 256 bytes every few seconds, I believe the mORMot 1 code will work for now. Let me know if I am flawed in my cost/benefit analysis of sticking with the working mORMot 1 websockets server for now.

Last edited by Paul117 (2024-04-26 07:19:55)

Offline

#6 2024-04-26 07:38:10

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,242
Website

Re: Can't find info on using TWebSocketAsyncServer for basic echo server

Why not use mORMot 2 directly?

Offline

Board footer

Powered by FluxBB