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

Atu*_*tul 3 sockets windows networking asynchronous tcp

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

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

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

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

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

现在问题是:

  1. 这样做是否正确?

  2. 如果是的话,多少钱

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

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

应该是好的,以获得最佳性能.

注:这是不是重复我以前的问题上同样的问题.但这更多的是关于验证解决方案,我在完成答案和链接之后得到了答案.

Rem*_*eau 5

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