0

MSDN 杂志 2005 年 8 月的这篇文章中,Daryn Kiely 解释了构建 TCP 服务器的三种方法。

第三种模型,异步模型,是最适合我需要的模型,但我对其内部工作的一些细节有一些了解。

问题 1 - 关于接受连接的线程数

在示例中,当通过调用启动服务器时Start(),代码会创建十个接受连接的线程池:

public void Start()
{
    SetupServerSocket();
    for (int i = 0; i < 10; i++)
        _serverSocket.BeginAccept(AsyncCallback(AcceptCallback), _serverSocket);
}

我不明白为什么你不能只使用一个_serverSocket.BeginAccept,为什么数字十。

问题 2 – 大约收到零字节

ReceiveCallback()中,如果我们收到零字节,我们将关闭连接。为什么?当接收到零字节时总是认为客户端关闭了连接?在我在这里进行的测试中,当我的客户端关闭连接时,我得到一个在 SocketException 中捕获的异常。我在这里错过了什么吗?

问题 3 – 关于重新开始接收的需要

在套接字中接收到某些内容后,它会被放回 BeginReceive。为什么我们需要重新开始接收?这不应该是自动的吗?

问题 4 – 关于缓冲区大小

使用 255 字节的缓冲区。我知道如果一条消息的长度大于缓冲区大小,它会在多个接收中分散。我应该设置一个足够大的缓冲区大小以保证没有消息会被碎片化,还是我必须提供代码来处理消息碎片(在一个缓冲区中加入多个接收)?

4

2 回答 2

3

问题 1 - 关于接受连接的线程数

在示例中,当通过调用 Start() 启动服务器时,代码会创建十个接受连接的线程池:

public void Start()
{
    SetupServerSocket();
    for (int i = 0; i < 10; i++)
        _serverSocket.BeginAccept(AsyncCallback(AcceptCallback), _serverSocket);
}

我不明白为什么你不能只使用一个_serverSocket.BeginAccept,为什么数字十。

没有理由产生几个BeginAccept这样的。只需调用一个新BeginAcceptAcceptCallback代替。

问题 2 – 大约收到零字节

在 ReceiveCallback() 中,如果我们收到零字节,我们将关闭连接。为什么?当接收到零字节时总是认为客户端关闭了连接?在我在这里进行的测试中,当我的客户端关闭连接时,我得到一个在 SocketException 中捕获的异常。我在这里错过了什么吗?

是的。0 字节表示正常断开连接。即对方先用Shutdown然后再Close直接关闭。

任何其他类型的断开连接都会产生异常。

问题 3 – 关于重新开始接收的需要

在套接字中接收到某些内容后,它会被放回 BeginReceive。为什么我们需要重新开始接收?这不应该是自动的吗?

不。例如,当您关闭服务器时,您不想再次阅读。其他客户端可能只想接收一次,处理数据然后断开连接。

问题 4 – 关于缓冲区大小

使用 255 字节的缓冲区。我知道如果一条消息的长度大于缓冲区大小,它会在多个接收中分散。我应该设置一个足够大的缓冲区大小以保证没有消息会被碎片化,还是我必须提供代码来处理消息碎片(在一个缓冲区中加入多个接收)?

一个发送byte[]总是可以被分成多个接收。单个接收也可以包含两个发送byte[]缓冲区。这就是 TCP 的工作原理。

您通常使用一个接收缓冲区,然后使用另一个缓冲区来构建消息。或者使用更大的缓冲区并通过offset在方法调用中使用更大的缓冲区来告诉 Receive 完成消息

于 2012-11-06T13:40:55.897 回答
2

好的,我去试试:

1)其中的一个单一BeginAccept意味着您的服务器套接字将不接受连接,直到在BeginAccept中调用下一个AcceptCallback,这不是立即调用,而是在完成一些工作之后调用。我认为数字 10 是任意的 - 这就像假脱机 10 接受或本质上能够同时接收多达 10 个传入连接请求。如果您不需要处理很多客户,我想一个BeginAccept仍然可以工作。

2)我不知道你用的是什么客户端,但我已经使用了与浏览器的套接字连接,当他们关闭连接时,他们确实喜欢发送和清空段(或者这是我看到的调试)作为通知关闭。如果这不再正确,有人可以纠正我,但似乎是检查这一点的好习惯。

3)嗯,它不是自动的。最好循环它以确保您不会错过任何东西。

4) 据我所知,Windows 没有 TCP 缓冲区大小的最大值,除非管理员指定。所以你可以假设增加它,但也许看看:套接字编程的好的缓冲区大小是多少?- 在评论中说你不应该尝试在一次接收中获取所有消息,因为它毕竟是一个流协议。

于 2012-11-06T13:33:48.247 回答