在this MSDN Magazine August 2005 article中,Daryn Kiely解释了构建TCP服务器的三种方法。
第三个模型,即异步模型,是最适合我的需求的模型,但是我在理解其内部工作的某些细节方面有些麻烦。
在此示例中,通过调用Start()
启动服务器时,代码创建了十个接受连接的ThreadPool:
public void Start()
{
SetupServerSocket();
for (int i = 0; i < 10; i++)
_serverSocket.BeginAccept(AsyncCallback(AcceptCallback), _serverSocket);
}
我不明白为什么您不能只使用一个_serverSocket.BeginAccept
,为什么不能使用十。
在ReceiveCallback()
中,如果我们收到零字节,则会关闭连接。为什么?当总是收到零字节时,是否认为客户端已关闭连接?在我这里所做的测试中,当客户端关闭连接时,我收到一个在SocketException中捕获的异常。我在这里想念什么吗?
在套接字中接收到某些内容后,将其放回BeginReceive。为什么我们需要再次开始接收?这不应该自动吗?
使用255个字节的缓冲区。我知道,如果一条消息的长度大于缓冲区的大小,则它将在多个接收中碎片化。我应该设置一个足够大的缓冲区大小以保证没有消息会被碎片化,还是我必须提供代码来处理消息碎片(将多个接收合并到一个缓冲区中)?
问题1-关于接受连接的线程数
在此示例中,通过调用Start()启动服务器时,代码创建了十个接受连接的ThreadPool:
public void Start()
{
SetupServerSocket();
for (int i = 0; i < 10; i++)
_serverSocket.BeginAccept(AsyncCallback(AcceptCallback), _serverSocket);
}
我不明白为什么您不能只使用一个_serverSocket.BeginAccept,为什么不使用十。
没有理由像这样产生几个BeginAccept
。只需在BeginAccept
中调用一个新的AcceptCallback
。
问题2 –大约收到零字节
在ReceiveCallback()中,如果我们收到零字节,则关闭连接。为什么?当总是收到零字节时,是否认为客户端已关闭连接?在我这里所做的测试中,当客户端关闭连接时,我收到一个在SocketException中捕获的异常。我在这里想念什么吗?
是。 0字节表示正常断开连接。也就是说,另一端首先使用Shutdown
,然后使用Close
,而不是直接关闭。
任何其他类型的断开连接都会产生异常。
问题3 –关于是否需要再次开始接收
在套接字中接收到某些内容后,将其放回BeginReceive。为什么我们需要再次开始接收?这不应该自动吗?
没有例如,当您关闭服务器时,您不想再次阅读。其他客户端可能只希望接收一次,处理数据然后断开连接。
问题4 –关于缓冲区大小
使用255个字节的缓冲区。我知道,如果一条消息的长度大于缓冲区的大小,则它将在多个接收中碎片化。我应该设置一个足够大的缓冲区大小以保证没有消息会被碎片化,还是我必须提供代码来处理消息碎片(将多个接收合并到一个缓冲区中)?
一个发送的byte[]
总是可以被伪装成多个接收。一个接收也可以包含两个发送的byte[]
缓冲区。这就是TCP的工作方式。
您通常使用一个接收缓冲区,然后再使用另一个来构建消息。或者使用更大的缓冲区,并通过在方法调用中使用更大的offset
来告诉Receive完成消息。
好吧,我去: