有关MSDN杂志中的TCP异步服务器的问题

时间:2012-11-06 12:56:44

标签: c# networking tcp tcpserver

this MSDN Magazine August 2005 article中,Daryn Kiely解释了构建TCP服务器的三种方法。

第三个模型,即异步模型,是最符合我需求的模型,但我对其内部工作的一些细节有一些麻烦。

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

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

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

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

问题2 - 关于收到零字节

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

问题3 - 关于再次开始接收的需要

在socket中收到一些东西后,它会被放回BeginReceive。为什么我们需要再次开始接收?这不应该是自动的吗?

问题4 - 关于缓冲区大小

使用255字节的缓冲区 据我所知,如果消息的长度大于缓冲区大小,则会在多个接收中分段。我应该设置一个足够大的缓冲区大小来保证没有消息会被分段,或者我必须提供代码来处理消息碎片(在单个缓冲区中加入多个接收)?

谢谢!

2 个答案:

答案 0 :(得分:3)

  

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

     

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

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的需要

     

在socket中收到一些东西后,它会被放回BeginReceive。为什么我们需要再次开始接收?这不应该是自动的吗?

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

  

问题4 - 关于缓冲区大小

     

使用255字节的缓冲区。   据我所知,如果消息的长度大于缓冲区大小,则会在多个接收中分段。我应该设置一个足够大的缓冲区大小来保证没有消息会被分段,或者我必须提供代码来处理消息碎片(在单个缓冲区中加入多个接收)?

一个发送byte[]的人总是可以进行多次接收。单个接收还可以包含两个发送的byte[]缓冲区。这就是TCP的工作原理。

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

答案 1 :(得分:2)

好吧,我要去吧:

1)那里的单BeginAccept意味着你的服务器套接字将不会接受连接,直到在BeginAccept中调用下一个AcceptCallback,而BeginAccept没有被立即调用但是而是在完成一些工作之后。我认为数字10是任意的 - 它就像假脱机10接受或实质上能够同时占用多达10个传入连接请求。如果你不需要处理很多客户,我想单个{{1}}仍然有用。

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

3)嗯,有点不自动。最好循环它以确保你不会错过任何东西。

4)据我所知,Windows没有TCP缓冲区大小的最大值,除非由admin指定。所以你可以增加它,但也许可以看看:What is a good buffer size for socket programming? - 在评论中说你不应该尝试在一次接收中获取所有消息,因为它毕竟是一个流协议。 / p>