我寻找满足以下要求的最佳实践:
- 以异步方式处理多个客户端套接字的框架
- 每个传入消息协议规定每个消息都是格式字符串,并用换行符“\n”标记为完整。
- 我可以完全控制客户端,但不能控制服务器端。服务器接受并发送带有换行符的基于字符串的消息以标记消息的完成。
- 我希望能够在任何给定时间通过每个连接的套接字发送消息(每个套接字都可以接收和发送消息)。
- 传入消息应通过回调转发。
- 我希望能够在我的实现中选择是否将来自所有连接的套接字的所有传入完整消息路由到一个回调,或者每个套接字客户端是否实现自己的回调。
- 我最多连接 4 个客户端/套接字。因此,我寻找利用如此有限数量的套接字的建议,但是能够同时管理所有这些。
我想知道我使用的框架BeginReceive
和EndReceive
实现的 IAsyncResult 回调是否是最先进的,因为我的目标是 .Net 4.5。是否有更好的解决方案,例如使用 NetworkStream 或其他 API 选择?BeginReceive/EndReceive 实现真正困扰我的是,在 EndReceive 之后我必须再次调用 BeginReceive 并再次注册回调。对我来说,这听起来像是一个可怕的开销。为什么不能在任何时候异步添加新数据,同时另一个上下文构建完整的消息,然后通过引发的事件进行路由?
使用 IAsyncResult 的论点通常是在处理线程处理时给出的,但与以下内容相反的是:使用 NetworkStream 并简单地从流中读取和写入。如前所述,仅交换字符串消息,并且每个协议的每个消息都由换行符标记为完成。一个单独的任务/线程将通过ReadLine()
. 它可能不会比这更简单,不是吗?
我基本上要问的是,如何才能使以下代码真正异步?
public class SocketClient
{
private TcpClient client;
private StreamReader reader;
private StreamWriter writer;
public event Action<string> MessageCallback;
public SocketClient(string hostname, int port)
{
client = new TcpClient(hostname, port);
try
{
Stream stream = client.GetStream();
reader = new StreamReader(stream);
writer = new StreamWriter(stream);
writer.AutoFlush = true;
//Start Listener on port
StartListener();
}
catch (Exception e)
{
throw new Exception(e.ToString());
}
}
public void StartListener()
{
Task task = Task.Factory.StartNew(() =>
{
while (true)
{
if (MessageCallback != null)
{
MessageCallback(reader.ReadLine());
}
//Thread.Sleep(200);
}
});
}
}