如何避免异步非阻塞WSASend调用上的缓冲区溢出

时间:2014-07-21 14:05:05

标签: windows sockets networking asynchronous tcp

这是关于在Windows上开发的TCP服务器。服务器将连接数千个客户端。服务器将继续以非阻塞异步方式向客户端发送随机大小的字节(可以说1到64KB之间的任何内容)。

目前,在致电WSASend之前,我没有任何约束或条件。我只是使用任何大小的缓冲区调用它,并在发送数据后接收回调(因为它是非阻塞调用)。

问题是,如果一个或几个客户端接收数据的速度很慢,最终我的服务器的内核缓冲区会变满,最后我会收到缓冲区溢出(WSAENOBUFS)错误。

为避免这种情况,我打算这样做:

如果服务器有(X)大小的内核缓冲区,并且如果连接的最大客户端数是(N)那么我只允许在每个客户端的套接字上写入(X)/(N)字节。 (因此,对于50K连接和内核缓冲区大小为128 MB,我每次只向每个套接字写入最多2684个字节)并且一旦我收到回调,我就可以发送下一组字节。 这种方式即使任何或少数客户端都很慢,也不会导致占用所有内核缓冲区及其待处理数据。

现在问题是:

  1. 这样做是否正确?

  2. 如果是,那么多少

    一个。内核缓冲区的大小(X)和

    湾允许的最大连接数(N),

  3. 应该很好,以获得最佳性能。

    注意:这是我之前question在同一问题上的重复。但这更多的是关于验证解决方案后我在得到答案之后出现的问题link我得到了答案。

2 个答案:

答案 0 :(得分:5)

在同一个套接字上没有多个WSASend()个未完成的调用。为传出数据维护自己的缓冲区。将数据放入缓冲区时,如果缓冲区先前为空,则将当前缓冲区内容传递给WSASend()。每次WSASend()完成时,它会告诉您它发送了多少字节,因此从缓冲区前面删除那么多字节,如果缓冲区不为空,则再次使用剩余内容再次调用WSASend()。虽然WSASend()正忙,但如果您需要发送更多数据,只需将其附加到缓冲区的末尾,让WSASend()在准备就绪时看到它。

答案 1 :(得分:-1)

让错误告诉你。这就是它的用途。只需继续发送直到出现错误,然后停止。