XSocket.net. how to send a message to a client from an object which is not a controller

StackOverflow https://stackoverflow.com/questions/21483298

  •  05-10-2022
  •  | 
  •  

Pregunta

I have a class that starts a server:

public class SocketServer
{
    private static IXSocketServerContainer server = null;

    public SocketServer()
    {
        server = XSockets.Plugin.Framework.Composable
                      .GetExport<IXSocketServerContainer>();
    }

    public bool StartServers()
    {
        try
        {
            server.StartServers();
            return true;
        } catch
        {
            return false;
        }
    }

this class has a method:

public void SendEventMessageToAllClients(string message)
{
    XSockets.Core.XSocket.Helpers.XSocketHelper
        .SendToAll<MyController>(new MyController(), message, "events");
}

where MyController is my own controller, it is implemented and the server can find it and this method work.

Now I would like to expand the functionality with a new method that allows me to send an event to an specific client:

    public void SendEventMessageToClient(string clientId, string message)
    {
        XSockets.Core.XSocket.Helpers.XSocketHelper
             .SendTo<MyController>(new MyController(), 
                                   p => p.ClientId == clientId, message, "events");
    }

Is this the right approach or am I doing something wrong?

Thanks!

¿Fue útil?

Solución 2

Uffe, you're right an the ClientPool is the right option for me, I had problems running your code because some of the mappings proposed by you are not working, here is your proposed solution slightly modified to make it run:

//Get a pool client
ClientPool poolClient = XSockets.Client.ClientPool.GetInstance("ws://127.0.0.1:4502/MyController", "*");

Methods for sending a message to the controller. ITextArgs are needed in this case

public void SendEventMessageToClient(Guid clientId, string message)
{
    ITextArgs textargs = new TextArgs(mess, "SendEventMessageToClient");        
    poolClient.Send(new {clientId = guid, message = "Hello to one client"}, "SendEventMessageToClient");
} 

Here, I TextArgs is not needed, it can be used, but string works also properly. It seems that the conversion to ITextArgs works fine here.

public void SendEventMessageToAllClients(string message)
{
    poolClient.Send("hello all", "SendEventMessageToAllClients");    
}

The controller: Only ITextArgs messages are mapped. Using string will not work.

public void SendEventMessageToClient(Guid clientId, ITextArgs message)
{
    c.SendTo(p => p.ClientId == clientId, message.data, "events");
} 


public void SendEventMessageToAllClients(ITextArgs message)
{
    c.SendToAll(message.data, "events");
}

Thanks you very much Uffe for your help!

Otros consejos

I would not recomend that approach, I have not even tested if that actaully works.

You create a new controller every time just to be able to access the extension method. I am guessing that since you have this on the class starting the server you only use this as a publisher?

If so the correct way would be to install the XSockets.Client package and use the client pool to publish messages: client pool documentation

Example with client pool

The nice thing about the client pool is that you do not need to create an instance every time. The pool will reuse your connection to the controller. Using the clientpool (or a real client connection) will ensure that the message pass through the Pipeline and all interceptors if you have any. Using a controller instance directly will never reach the pipline, interceptors etc.

//Get a pool client
ClientPool poolClient =
        XSockets.Client.ClientPool.GetInstance("ws://127.0.0.1:4502/MyController", "*");

Methods for sending a message to the controller.

public void SendEventMessageToClient(Guid clientId, string message)
{        
    poolClient.Send(new {clientId, message}, "SendEventMessageToClient");
} 


public void SendEventMessageToAllClients(string message)
{
    poolClient.Send(message, "SendEventMessageToAllClients");    
}

The controller

public void SendEventMessageToClient(Guid clientId, string message)
{
    this.SendTo(p => p.ClientId == clientId, message, "SendEventMessageToClient");
} 


public void SendEventMessageToAllClients(string message)
{
    this.SendToAll(message, "SendEventMessageToAllClients");
}

Example with instance of controller

If you decide to use the way you have done you should at least create on ONE instance of the controller to use the in the server class.

Important: Using a controller instance directly will never reach the pipline, interceptors etc.

//Be aware of the fact that this controller NEVER will have a connection.
//It can only send to others, it can never receive messages!
MyController c = new MyController();

//You should probably have a Guid here instead of string
//Also note that the client have to subscribe for "events" to get the message
public void SendEventMessageToClient(Guid clientId, string message)
{
    this.SendTo(p => p.ClientId == clientId, message, "SendEventMessageToClient");
} 


public void SendEventMessageToAllClients(string message)
{
    this.SendToAll(message, "SendEventMessageToAllClients");
}

Since I do not know what you are trying to accomplish Im not sure this is the best way, but one of the merhods above should work.

EDIT: Also, in a real application you probably dont have access to the MyController class since it probably is in a separate assembly not being referenced at compile time. So then you approach will not even be possible and the way to go then is client or clientpool

/Uffe

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top