如何在.NET客户端中通过SignalR发送大数据

问题描述 投票:0回答:5

我们有一个.NET客户端,使用SignalR调用Server方法,但参数似乎很大,对于这种情况如何修复?

客户端代码:

public async Task FooAsync()
{
    var hubConnection = new HubConnection(...);
    await hubConnection.Start();

    var hubProxy = hubConnection.CreateHubProcx("ValueHub");
    //the content is very long, about 11776065 bytes (11MB)
    var content = File.ReadAllText(...);
    hubProxy.Invoke("Send", content);
    ...
}

服务器代码:

[HubName("ValueHub")]
public class ValueHub : Hub
{
    public void Send(string json)
    {

    }
}

从异常堆栈和源代码中,我发现SignalR内部使用

HttpClient
FormUrlEncodedContent
类型
HttpContent
,也许限制就来自这里。

System.UriFormatException was unhandled
  HResult=-2146233033
  Message=Invalid URI: The Uri string is too long.
  Source=System
  StackTrace:
       at System.UriHelper.EscapeString(String input, Int32 start, Int32 end, Char[] dest, Int32& destPos, Boolean isUriString, Char force1, Char force2, Char rsvd)
       at System.Uri.EscapeDataString(String stringToEscape)
       at System.Net.Http.FormUrlEncodedContent.Encode(String data)
       at System.Net.Http.FormUrlEncodedContent.GetContentByteArray(IEnumerable`1 nameValueCollection)
       at System.Net.Http.FormUrlEncodedContent..ctor(IEnumerable`1 nameValueCollection)
       at Microsoft.AspNet.SignalR.Client.Http.DefaultHttpClient.Post(String url, Action`1 prepareRequest, IDictionary`2 postData, Boolean isLongRunning)
       at Microsoft.AspNet.SignalR.Client.Transports.HttpBasedTransport.Send(IConnection connection, String data, String connectionData)
       at Microsoft.AspNet.SignalR.Client.Transports.AutoTransport.Send(IConnection connection, String data, String connectionData)
       at Microsoft.AspNet.SignalR.Client.Connection.Send(String data)
       at Microsoft.AspNet.SignalR.Client.Hubs.HubProxy.Invoke[T](String method, Object[] args)
       at Microsoft.AspNet.SignalR.Client.Hubs.HubProxy.Invoke(String method, Object[] args)

针对这个问题有什么好的建议吗?

c# asp.net signalr signalr.client
5个回答
21
投票

您可以在 Startup.cs 中添加一行,通过将 MaxIncomingWebSocketMessageSize 设置为 null 来使消息大小“无限”:

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
        app.MapSignalR();
        GlobalHost.Configuration.MaxIncomingWebSocketMessageSize = null;
        }
    }
} 

我的数据量约为 200kb,持续发送 10 条消息。 我不知道如果每秒发送更多数据,它的效果如何。


7
投票

正如您已经收集到的 - 对于 SIGNALR 自己的设计来说,这些数据太多了。

使用另一个进程使用普通的 REST API (GET/POST) 来执行此操作不是一个更好的主意吗?也许是一条消息,向用户表明需要完成此操作,因为这感觉非常“批量”。

其次,如果这是一个要求(可能是工作的错误工具),您是否考虑过压缩。


5
投票

很容易做到..

  • 将文件分割成字节数组块(我的测试显示每个块最大 10kb 就足够了)
  • 使用类似的调用将块发送到客户端(计算

    totalBytes
    和您拥有的块数据):

    hubProxy.Invoke("Send", chunk,currentBytes,totalBytes);
    
  • 从客户端获取块并创建一个字节数组并附加每个块,信号器同步发送文件,这意味着数据将按照您的发送顺序接收
  • 您有
    totalbytes
    currentBytes
    数据,现在您知道收到的所有数据,将此字节数组保存到带有流或任何您喜欢的文件中..

2
投票

将其添加到网络配置中

<httpRuntime maxRequestLength="1048576" executionTimeout="600" />

然后将此代码添加到 Startup.cs

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.MapSignalR();
        GlobalHost.Configuration.MaxIncomingWebSocketMessageSize = null;
    }
}

0
投票

从 aspnetcore3.1+ 开始,我们有了 SignalR 流。如果您正在将文件读取为大字符串,就像您的示例一样,我会使用 channel

注意:如果您使用 MessagePack,您可以压缩 SignalR 连接并在线路上发送更少的数据。

与旧的接受答案相反,SignalR 现在能够有效地发送大数据流。

客户端代码:

public async Task FooAsync()
{
    var hubConnection = new HubConnection(...);
    await hubConnection.Start();

    var hubProxy = hubConnection.CreateHubProcx("ValueHub");
    var channel = Channel.CreateBounded<string>(1);
    await hubProxy.Invoke("Send", channel.Reader);

    var content = File.ReadAllText(...);
    await channel.Writer.WriteAsync(content);
    channel.Writer.Complete();
    ...
}

服务器代码:

[HubName("ValueHub")]
public class ValueHub : Hub
{
    public void Send(ChannelReader<string> stream)
    {
        while (await stream.WaitToReadAsync())
        {
            while (stream.TryRead(out string item))
            {
                // do something with the stream item
               
            }
        }
    }

© www.soinside.com 2019 - 2024. All rights reserved.