C# 服务器 - TCP/IP 套接字效率

标签 c# multithreading sockets tcp nagle

大家好!

我正在为一个封闭源代码的游戏开发一个开源服务器——该游戏使用 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/

相关文章:

c# - 在 C# 中使用变量作为文本框名称的一部分

c# - Json反序列化和ADO持久化过程中的字符串截断

linux - 使用 sigmask 将信号传递给多线程程序

C++ 静态类成员指的是自身

sockets - Linux : Unix domain datagram sockets don't follow specification of connect/recv,吗?

c - 多播监听器接受另一个端口上的套接字

Python 套接字和 Opencv - ConnectionResetError : [WinError 10054]

c# - XAML 相当于 CSS 中的对象位置

c# - ASP.NET 自动生成 aspx.designer.cs 关闭?

java - 无限期地等待可能永远不会到达的消息