c# - 关于so​​ckets的listening和backlog的问题

标签 c# sockets server-side

我正在用 C# 编写一个需要处理传入连接的应用程序,而且我以前从未进行过服务器端编程。这让我想到以下这些问题:

  • 高积压/低积压的优缺点?为什么我们不应该将积压工作设置为一个巨大的数字?
  • 如果我调用 Socket.Listen(10),在 10 个 Accept() 之后我是否必须再次调用 Listen()?还是我必须在每次 Accept() 之后调用 Listen()?
  • 如果我将 backlog 设置为 0,假设有两个人想同时连接到我的服务器,会发生什么? (我在循环中调用 Socket.Select 并检查监听套接字的可读性,在处理完第一个连接后,如果我再次调用 Listen(),第二个连接是否会在下一次迭代时成功?)

提前致谢。

最佳答案

监听积压是,as Pieter said ,一个队列,操作系统使用它来存储已被 TCP 堆栈接受但尚未被您的程序接受的连接。从概念上讲,当客户端连接时,它会被放置在这个队列中,直到您的 Accept() 代码将其删除并将其交给您的程序。

因此,listen backlog 是一个调整参数,可用于帮助您的服务器处理并发连接尝试的峰值。请注意,这与并发连接尝试的峰值有关,与您的服务器可以维护的最大并发连接数无关。例如,如果您的服务器每秒接收 10 个新连接,那么调整监听积压不太可能产生任何影响,即使这些连接存在很长时间并且您的服务器支持 10,000 个并发连接(假设您的服务器未达到最大值)出服务于现有连接的 CPU!)。但是,如果服务器偶尔在每秒接受 1000 个新连接时遇到短时间,那么您可以通过调整监听积压以提供更大的队列来防止某些连接被拒绝,从而让您的服务器有更多时间调用 Accept() 为每个连接。

至于优点和缺点,优点是您可以更好地处理并发连接尝试的峰值,相应的缺点是操作系统需要为监听积压队列分配更多空间,因为它更大。所以这是性能与资源的权衡。

就我个人而言,我将 listen backlog 设为可以通过配置文件进行外部调整的东西。

调用 listen 和 accept 的方式和时间取决于您使用的套接字代码的风格。使用同步代码,您将使用一个值(比如 10)调用一次 Listen(),用于监听积压,然后循环调用 Accept()。对 listen 的调用设置了您的客户端可以连接到的端点,并在概念上创建了指定大小的监听积压队列。调用 Accept() 从监听积压队列中删除挂起的连接,设置应用程序使用的套接字并将其作为新建立的连接传递给您的代码。如果您的代码调用 Accept()、处理新连接并循环再次调用 Accept() 所花费的时间长于并发连接尝试之间的间隔然后您将开始在监听积压队列中积累条目。

对于异步套接字,它可能会有点不同,如果您使用异步接受,您将像以前一样监听一次,然后发布多个(同样可配置的)异步接受。随着其中每一个的完成,您将处理新连接并发布新的异步接受。通过这种方式,您有一个监听积压队列和一个挂起的接受“队列”,因此您可以更快地接受连接(更重要的是,异步接受是在线程池线程上处理的,因此您没有一个紧密的接受循环)。这通常更具可扩展性,并为您提供两点调整以处理更多并发连接尝试。

关于c# - 关于so​​ckets的listening和backlog的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4253454/

相关文章:

c# - 在自定义类中为 Entity Framework 实现IDisposable

c# - 如何从 C# 中的 JSON 字符串中获取一些值?

c# - StreamReader.EndOfStream产生IOException

linux - Linux 中 WSAEvent 的等价物是什么?

java - 多线程Java服务器

c# - .Net 核心起订量 : An expression tree may not contain a call or invocation that uses optional arguments

c# - 如何判断拖放操作是否失败?

java - GWT Java - 服务器端 "for loop"不工作

css - 如何将 CSS 应用于 JPG 服务器端?

java - UTF-8 |表单提交中的特殊字符问题 | java.io.CharConversionException异常