2

我有一个启动服务器的类:

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;
        }
    }

这个类有一个方法:

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

我自己的控制器在哪里MyController,它已实现并且服务器可以找到它并且此方法有效。

现在我想使用一种新方法来扩展功能,该方法允许我向特定客户端发送事件:

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

这是正确的方法还是我做错了什么?

谢谢!

4

2 回答 2

7

我不会推荐这种方法,我什至没有测试过这种方法是否有效。

您每次都创建一个新控制器只是为了能够访问扩展方法。我猜,既然你在启动服务器的类上有这个,你只用它作为发布者?

如果是这样,正确的方法是安装 XSockets.Client 包并使用客户端池发布消息:客户端池文档

客户端池示例

客户端池的好处是您不需要每次都创建一个实例。池将重用您与控制器的连接。使用客户端池(或真正的客户端连接)将确保消息通过管道和所有拦截器(如果有)。直接使用控制器实例永远不会到达管道、拦截器等。

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

向控制器发送消息的方法。

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


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

控制器

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


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

控制器实例示例

如果您决定使用您已经完成的方式,您至少应该在控制器的一个实例上创建以在服务器类中使用。

重要提示:直接使用控制器实例永远不会到达管道、拦截器等。

//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");
}

由于我不知道您要完成什么我不确定这是最好的方法,但是上面的方法之一应该可以工作。

编辑:另外,在一个真实的应用程序中,您可能无法访问 MyController 类,因为它可能位于一个单独的程序集中,在编译时没有被引用。那么你的方法甚至是不可能的,那么要走的路就是客户端或客户端池

/乌菲

于 2014-02-01T07:25:22.783 回答
0

Uffe,你是对的,ClientPool 对我来说是正确的选择,我在运行你的代码时遇到了问题,因为你提出的一些映射不起作用,这里是你提出的解决方案稍作修改以使其运行:

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

向控制器发送消息的方法。在这种情况下需要 ITextArgs

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

在这里,我不需要 TextArgs,它可以使用,但字符串也可以正常工作。似乎转换为 ITextArgs 在这里工作正常。

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

控制器:仅映射 ITextArgs 消息。使用字符串将不起作用。

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");
}

非常感谢你的帮助!

于 2014-02-03T09:49:37.717 回答