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

时间:2015-08-04 13:54:33

标签: c# multithreading sockets tcp nagle

美好的一天!

我正在为一个闭源游戏开源服务器 - 游戏使用TCP / IP套接字(而不是UDP,doh ......)运行。因此,作为基于连接的协议,我无法使用此

我目前的计划结构(愚蠢):

  

核心线程

     
      
  • 接收新连接并创建新的客户端对象。
  •   
  

客户对象

     
      
  • IOloop(在自己的线程上运行)

         
        
    • 从套接字获取数据,处理数据包。 (一次一个包)
    •   
    • 发送从其他线程缓冲的数据(一次一个数据包)
    •   
  •   

客户端将自动发送数据(无延迟)。

我注意到程序的一个巨大缺陷,主要是它发送的数据非常慢。因为我同步发送数据包。 (Socket.Send(byte [] buffer))

我想几乎立即发送数据,没有延迟 - 异步。

我每次想要发送一个数据包时都尝试创建一个新线程(所以每个数据包都在它自己的托管线程上发送),但这真是一团糟。

我当前的系统使用禁用nagle算法的同步发送 - 但这有瓶颈的缺陷 - 发送一个数据包,发送操作块直到TCP确认,然后发送下一个...我可以每100ms轻松发出10个数据包,如果数据包需要400毫秒发送,这将备份并中断。当然,在我的本地主机上,我没有遇到这个问题。

所以,我的问题是:发送多个小数据包的最佳方法是什么?我正在考虑将每个IO线程循环结束时发送的数据合并到一个大字节缓冲区,以减少来回延迟 - 但这里明显的问题是这会破坏我希望会停止的nagle算法避免延迟。

同步发送如何工作?在我相信收件人是否正确收到数据之前,它是否会阻止?有没有办法可以在不等待确认的情况下完成这项工作?我知道数据包必须按顺序正确地进行(根据协议规范)。

1 个答案:

答案 0 :(得分:0)

我做了一些研究,现在我正在使用当前的系统:

使用AsyncCallbacks进行无线程的异步发送/接收操作。

所以我让服务器启动一个读操作,然后回调直到完成,当收到一个数据包,它被处理,然后一个新的读操作将开始......

这种方法大大减少了系统开销 - 线程池,内存等。

我使用了以下一些方法并根据自己的喜好自定义:https://msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx

非常高效,强烈推荐这种方法。对于任何TCP / IP网络应用程序,低延迟非常重要,异步回调是最好的方法。