我想使用NetworkStream
(或者也许Socket
)来读/写 TCP 连接。我想使用非阻塞操作,这样我就不必处理多个线程,或者处理如果某些线程可能因阻塞网络操作而停止时如何停止程序的问题。
NetworkStream.Read的文档暗示它是非阻塞的(“如果没有数据可用于读取,则 Read 方法返回 0”),所以我想我不需要异步回调来读取......对吗?
但是写作呢?好吧,微软有一个关于这个主题的通常的低质量教程,他们建议AsyncCallback
为每个操作编写一个繁琐的方法。这个回调中的代码有什么意义?
client.BeginSend(byteData, 0, byteData.Length, SocketFlags.None,
new AsyncCallback(SendCallback), client);
...
private static void SendCallback(IAsyncResult ar)
{
try {
Socket client = (Socket)ar.AsyncState;
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
的文档AsyncCallback
说它是“异步操作完成时调用的回调方法”。如果操作已经完成,为什么还要调用Socket.EndSend(IAsyncResult)
?同时,文档NetworkStream.BeginWrite
说“您必须创建一个实现AsyncCallback
委托的回调方法并将其名称传递给该BeginWrite
方法。您的状态参数至少必须包含NetworkStream
.”
但为什么“必须”我呢?我不能只是存储在IAsyncResult
某个地方...
_sendOp = client.BeginSend(message, 0, message.Length, SocketFlags.None, null, null);
...并定期检查是否完成?
if (_sendOp.IsCompleted)
// start sending the next message in the queue
(我知道这意味着轮询,但它将在预计大部分时间处于活动状态的服务器中,并且我计划在空闲时进行一些 Thread.Sleeps。)
另一个问题。我发送的消息被分解为一个头数组和一个正文数组。我可以连续发出两个 BeginWrites 吗?
IAsyncResult ar1 = _stream.BeginWrite(header, 0, header.Length, null, null);
IAsyncResult ar2 = _stream.BeginWrite(msgBody, 0, msgBody.Length, null, null);
此外,欢迎任何关于是否使用 Socket 或 NetworkStream 的意见。