我正在使用一个使用TcpListener
对象的异步TCP服务器类。我对BeginAcceptTcpClient
使用TcpListener
方法,当回调触发并EndAcceptTcpClient
时,我得到一个TcpClient
对象。为了接收和发送此TcpClient
,我需要使用客户端对象提供的NetworkStream
。
我使用NetworkStream
的方式虽然感觉不对。我调用BeginRead
和回调最终使用EndRead
,但这要求我使用byte[]
缓冲区。到目前为止,这对我来说运作良好,但我不得不怀疑是否有更清洁的做事方式。我目前的流程如下:receive data into a byte[] buffer,throw data into a MemoryStream
,use a BinaryReader
to get the data that I'm passing,然后我最终可以得到我的协议所需的内容。
是否有更优雅的方式从NetworkStream
转到BinaryReader
(最终BinaryWriter
,因为我要按照收到的数据传回数据)?我必须首先将其转储到byte[]
,然后转换为MemoryStream
(复制数据吗?),然后最终能够创建读取器/写入器对象,这是浪费的。
我选择使用BinaryReader
创建BinaryWriter
/ NetworkStream
,但是从我收集的内容来看,这些对象需要一个包含以前可用数据的流。似乎我只需要通知某种方式即可获得NetworkStream
数据可用而无需读入缓冲区。也许我错了,这正是NetworkStreams
应该如何使用的。如果我不必将缓冲区从一个流复制到另一个流中,那么事情似乎可以更加简化。
编辑:
以下是相关来源的示例:
public class Server
{
TcpListener listener;
const int maxBufferSize = 0xFFFF;
byte[] clientBuffer = new byte[maxBuffersize];
public Server(IPAddress address, int port)
{
listener = new TcpListener(address, port);
}
public void Start()
{
listener.Start();
listener.BeginAcceptTcpClient(OnAccept, listener);
}
public void Stop()
{
listener.Stop();
}
private void OnAccept(IAsyncResult ar)
{
TcpListener listener = ar.AsyncState as TcpListener;
TcpClient client = listener.EndAcceptTcpClient(ar);
client.GetStream().BeginRead(clientBuffer, 0, maxBufferSize, OnReceive, client);
listener.BeginAcceptTcpClient(OnAccept, listener);
}
private void OnReceive(IAsyncResult ar)
{
TcpClient client = ar.AsyncState as TcpClient;
int len = client.GetStream().EndRead(ar);
if (len == 0)
{
client.Close();
return;
}
else
{
MemoryStream inStream = new MemoryStream(len == maxBufferSize ? clientBuffer : clientBuffer.Take(len).ToArray());
MemoryStream outStream = DoStuff(inStream); //Data goes off to the app at this point and returns a response stream
client.GetStream().Write(outStream.ToArray(), 0, outStream.Length);
inStream.Dispose();
outStream.Dispose();
}
}
}
我的问题围绕着OnReceive
中发生的事情。您将看到我使用EndRead
完成读取操作,此时我现在可以从Server类的byte []字段中检索数据。我担心的是,将数据从NetworkStream复制到数组,然后再复制到MemoryStream所花费的时间是浪费的(至少感觉就是这样,也许C#可以有效地处理这些东西?)
提前致谢。