如何.net任务并行库数据流发送消息到多个客户端,而不是只有一个缓存

本文关键字:客户端 缓存 有一个 并行 任务 net 数据流 消息 如何 | 更新日期: 2023-09-27 18:16:29

有一个Server Task,它使用TPL Dataflow向多个client Task发送消息。

  • 客户端随机连接到服务器
  • 客户端可以向服务器发送消息,客户端可以从服务器接收消息

服务器使用BufferBlock<string>向客户端发送消息,当客户端连接到服务器时,它从该BufferBlock<string>接收消息。

但是这个BufferBlock<string>只能缓存一条消息,客户端不能向服务器请求一条以上的消息,并且客户端不能设置一个条件来选择接收哪条消息。

我想要一个block类型,它可以缓存多个消息;并且客户端不仅可以从该块类型中读取一条消息,还可以选择接收哪条消息;

我尝试了其他TPL Dataflow block类型,但没有人有这样的能力,TPL Dataflow block是否不适合这样的要求?

条件很简单,每条消息都有一个时间戳,客户端只发送一个时间戳给服务器,然后服务器返回在时间戳之后发送的消息。

using System;
using System.Web;
using System.Net;
using System.Threading.Tasks;
using System.Text;
using SimpleJSON;
using System.Collections.Generic;
using System.Threading.Tasks.Dataflow;
namespace TestHttp
{
    public class HttpServer
    {
        private HttpListener httpListener;
        public Task task;
        public HttpServer()
        {
            var ta = Task.Factory.StartNew(RunHttp);
            task = ta.Result;
        }
        private async Task RunHttp()
        {
            var httpPort = 9090;
            httpListener = new HttpListener();
            httpListener.Prefixes.Add("http://*:"+httpPort+"/");
            httpListener.Start();
            while (httpListener.IsListening)
            {
                var context = await httpListener.GetContextAsync();
                var req = context.Request;
                Handle(context, req);
            }
            httpListener.Stop();
            httpListener.Close();
        }
        private async Task Handle(HttpListenerContext context, HttpListenerRequest req)
        {
            Console.WriteLine(req.RawUrl);
            var resp = await HandleGet(req);
            var buf = Encoding.UTF8.GetBytes(resp);
            context.Response.AddHeader("Content-Encoding", "utf-8");
            context.Response.ContentEncoding = Encoding.UTF8;
            context.Response.ContentLength64 = buf.Length;
            try
            {
                context.Response.OutputStream.Write(buf, 0, buf.Length);
            }
            catch (Exception exp)
            {
                Console.WriteLine(exp.ToString());
            }
            finally
            {
                context.Response.OutputStream.Close();
            }
        }
        private BufferBlock<string> messages = new BufferBlock<string>();
        private async Task<string> HandleGet(HttpListenerRequest req)
        {
            var r = req.RawUrl.Split('?');
            if (r[0] == "/send")
            {
                await messages.SendAsync(r[1]);
                return "Suc";
            }
            else if(r[0] == "/receive"){
                var timestamp = Convert.ToInt32(r[1]);
                var ret = await messages.ReceiveAsync();
                return ret;
            }
            //Console.WriteLine(r[0]);
            return "Error";
        }
    }
}

如何.net任务并行库数据流发送消息到多个客户端,而不是只有一个缓存

为什么说BufferBlock只能包含一个值?这不是真的,它可以包含尽可能多的消息,基于块创建选项,特别是BoundedCapacity选项。默认值为-1,代表无限容量。

因此,在客户端连接的那一刻,您可以轻松地获得通过时间戳过滤的所有消息,并将它们返回给客户端。这可能会导致更改客户机请求的结果值的签名,因为您必须提供TimeStamp参数,并提供返回消息的List<T>(而不是唯一的一个)的能力。没有任何代码,我们不能说更多关于这个问题

我认为TPL数据流块无法满足这样的要求。

我只是使用一个列表来保存所有的消息List<Message> messages;

struct Message  {
   int id;
   string msg;
}

和我需要使用锁或演员模型类似的邮箱,来处理我的客户端对List<Message>的请求。