大家好!
我正在为一个封闭源代码的游戏开发一个开源服务器——该游戏使用 TCP/IP 套接字(而不是 UDP,doh...)运行,所以作为一个基于连接的协议(protocol),我不得不使用这个。
我当前的程序结构(简单化):
Core Thread
- Receive new connection and create a new client object.
Client Object
IOloop (runs on its own thread)
- Get data from socket, process packets. (one packet at a time)
- Send data buffered from other threads (one packet at a time)
当它是自己的线程时,客户端将立即(无延迟)发送数据。
我注意到这个程序有一个很大的缺陷,主要是它发送数据的速度非常慢。因为我同步地逐包发送数据。 (Socket.Send(byte[] buffer))
我想几乎立即发送数据,没有延迟 - 异步。
每次我想发送一个数据包时,我都尝试创建一个新线程(这样每个数据包都在它自己的托管线程上发送),但这是一个巨大的困惑。
我目前的系统使用禁用nagle算法的同步发送——但这有瓶颈的缺陷——发送一个数据包,发送操作 block 直到TCP确认,然后发送下一个……我可以每100毫秒轻松发出10个数据包,如果数据包需要 400 毫秒才能发送,这就会备份并中断。当然,在我的本地主机上我没有遇到这个问题。
那么,我的问题是:发送多个小数据包的最佳方式是什么?我正在考虑合并数据以在每个 IO 线程循环结束时发送到一个大字节缓冲区,以减少来回延迟 - 但这里明显的问题是这破坏了我希望阻止的 nagle 算法避免延误。
同步发送是如何工作的?在我相信收件人确认正确接收数据之前,它是否会阻止?有没有办法不用等待确认就可以做到这一点?我知道数据包必须全部按顺序正确发送(根据协议(protocol)规范)。
最佳答案
我做了一些研究,现在正在使用当前系统:
没有线程的异步发送/接收操作,使用 AsyncCallbacks。
所以我让服务器启动一个读取操作,然后回调直到完成,当收到一个数据包时,它被处理,然后一个新的读取操作将开始...
这种方法大大减少了系统开销——线程池、内存等。
我使用了以下的一些方法并根据自己的喜好进行了定制:https://msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx
非常有效,强烈推荐这种方法。对于任何 TCP/IP 网络应用程序,低延迟都非常重要,异步回调是实现这一点的最佳方式。
关于C# 服务器 - TCP/IP 套接字效率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31811259/