You are not logged in.
Hi ab, I am using websocket in an application where the client is a web page and the server is a Delphi application (based on sample 31 echo server), the web client start the communication and the server responds.
My problem is that the server need send notification to web client and I don't know how send this with no current request from client side.
Is this possible ? with any example I would be grateful.
Thanks in advance.
EMartin.
Esteban
Offline
You can just call the SendFrame() method of the TWebSocketProtocolChat/TWebSocketProtocol class.
It is thread-safe, so could be called from any server thread, to notify the client.
Online
I tried that, but how I access to the instance of the TWebSocketProtocolChat and to the first parameter of SendFrame THttpServerResp ?.
Thanks..
Esteban
Offline
I solved this saving reference from TWebSocketProtocolChat and THttpServerResp:
// protocol class implementation
TCCAgentWSProtocol = class(TWebSocketProtocolChat)
protected
procedure ProcessFrame(Sender: THttpServerResp; const Frame: TWebSocketFrame);
public
CCAgentWS: TCCAgentWS; // my class using websocket protocol class
end;
// ProcessFrame implementation
procedure TCCAgentWSProtocol.ProcessFrame(Sender: THttpServerResp; const Frame: TWebSocketFrame);
begin
case Frame.opcode of
focContinuation:
begin
CCAgentWS.fWSProtocol := Self;
CCAgentWS.fWSHttpServerResp := Sender;
end;
focConnectionClose:
begin
CCAgentWS.fWSProtocol := Nil;
CCAgentWS.fWSHttpServerResp := Nil;
end;
...
end;
end;
It is not a mORMot solution but "it is what it is".
Thanks.
Esteban
Offline
I have a connections list that contains a list with all clients connections. I've created a OnAfterAddConnection event to capture Connection ID/Sock ID.
Every time a Client establishes a WebSocket connection, this connection is identified by a ConnectionID, and a sock ID, so I think I could use this info to send a message to a single client, but unfortunately I couldn't find a way.
IP Connection ID Sock ID
------------------------------------------
127.0.0.1 1 800
127.0.0.1 2 820
127.0.0.1 3 824
-------------------------------------------
It also would be nice to have a OnBeforeRemoveConnection to get the ConnectionID/SockID. Every time a WebSocket connection is dropped, this event is fired, to refresh the grid, for instance...
Does anyone have any suggestion how to:
How to broadcast: sends a message to all connected clients?
How to use SendFrame to send a message to a single client?
How to use SendFrame to disconnect a client?
Offline
Hello EMartin,
You could share your complete solution ?
I do not understand is what your class " TCCAgentWS " ...
I appreciate all the guidance you can provide .
I solved this saving reference from TWebSocketProtocolChat and THttpServerResp:
// protocol class implementation TCCAgentWSProtocol = class(TWebSocketProtocolChat) protected procedure ProcessFrame(Sender: THttpServerResp; const Frame: TWebSocketFrame); public CCAgentWS: TCCAgentWS; // my class using websocket protocol class end; // ProcessFrame implementation procedure TCCAgentWSProtocol.ProcessFrame(Sender: THttpServerResp; const Frame: TWebSocketFrame); begin case Frame.opcode of focContinuation: begin CCAgentWS.fWSProtocol := Self; CCAgentWS.fWSHttpServerResp := Sender; end; focConnectionClose: begin CCAgentWS.fWSProtocol := Nil; CCAgentWS.fWSHttpServerResp := Nil; end; ... end; end;
It is not a mORMot solution but "it is what it is".
Thanks.
Offline
Imho you are trying to solve that problem on the wrong application tier. TWebSocketProtocolChat.ProcessFrame is very low level. That's the reason why you are facing that problem at all.
Taking the chat service as example, there is:
procedure TChatService.Join(const pseudo: string; const callback: IChatCallback);
Put the callback parameter together with session params you can retrieve from global threadvar ServiceContext in some kind of simple data object/record. Store that object/record to any kind of list/array instead of "fConnected: array of IChatCallback". You can identify single sessions by searching the array/list now. The found data record/object has a direct reference to the IChatCallback. You have direct access to its functions for this single client connection.
Offline
You can just call the SendFrame() method of the TWebSocketProtocolChat/TWebSocketProtocol class.
It is thread-safe, so could be called from any server thread, to notify the client.
Hello AB,
I'm trying to use it like this:
type
//simple chatting protocol
TSimpleChatProtocol = class(TWebSocketProtocolChat)
private
fParent: TSimpleChatServer;
protected
procedure echoFrame(Sender: THttpServerResp; const Frame: TWebSocketFrame);
constructor newSimpleChatProtocol(aParent: TSimpleChatServer; const aName: RawUTF8);
end;
TSimpleChatServer = class
private
fPort: SockString;
fServer: TWebSocketServer;
fProtocol: TSimpleChatProtocol;
...
...
function TSimpleChatServer.closeConnetionOfClient(
aClient: THttpServerResp): Boolean;
var
frm: TWebSocketFrame;
begin
FrameInit(focConnectionClose, '', '', frm);
result :=fProtocol.SendFrame(aClient, frm);
end;
...
No effect is caused, any suggestions?
Last edited by cgsousa21 (2021-11-17 19:49:30)
Offline