为什么我应该使用非阻塞或阻塞套接字

Why should I use non-blocking or blocking sockets?

本文关键字:套接字 我应该 为什么      更新时间:2023-10-16

首先,我必须问哪个州最好?例如实时MMORPG服务器。如果我为每个客户端创建一个线程而不是使用非阻塞套接字怎么办?或者如果我使用一个包含所有非阻塞套接字的线程怎么办?你能解释一下我的优点吗?

你的问题值得一个更长的讨论,但这里有一个简短的答案:

    使用阻塞套接字
  • 意味着在任何线程中任何时候都可能只有一个套接字处于活动状态(因为它在等待活动时阻塞(
  • 使用阻塞套接字
  • 通常比非阻塞套接字更容易(异步编程往往更复杂(
  • 您可以按照您的要求为每个套接字创建 1 个线程,但与非阻塞解决方案相比,线程有开销并且效率极低;
  • 使用非阻塞套接字,您可以处理更大的客户端量:它可以在单个进程中扩展到数十万 - 但代码变得有点复杂

使用非阻塞套接字(在 Windows 上(,您有以下几种选择:

  • 投票
  • 基于事件
  • 重叠的 I/O

重叠的 I/O 将为您提供最佳性能(数千个套接字/进程(,但代价是成为正确理解和实现的最复杂的模型。

基本上,它归结为性能与编程复杂性。

注意

以下是为什么使用线程/套接字模型是一个坏主意的更好解释:

在 Windows 中,创建大量线程效率非常低,因为调度程序无法正确确定哪些线程应该接收处理器时间,哪些不应该。再加上每个线程的内存开销,意味着在处理套接字连接的容量耗尽之前很久,您将在操作系统级别耗尽内存(由于堆栈空间(和处理器周期(因为管理线程的开销(。

我会记录在案,除了玩具程序之外的几乎所有内容,您都应该理所当然地使用非阻塞套接字。

阻塞

套接字会导致一个严重的问题:如果另一端的计算机(或您与其连接的任何部分(在阻塞调用期间失败,您的代码最终将被阻塞,直到 IP 堆栈超时。在典型情况下,这大约是 2 分钟,这对于大多数目的来说是完全不可接受的。中止阻塞调用的唯一方法1 是终止发出它的线程 - 但终止线程本身几乎总是不可接受的,因为基本上不可能在它之后清理并回收它分配的任何资源。非阻塞套接字使得在需要时中止调用变得简单,而无需对进行调用的线程执行任何操作。

如果您改用多进程模型,则可以使阻塞套接字正常工作。在这里,您只需为每个连接生成一个全新的进程。该进程使用阻塞套接字,当/如果出现问题时,您只需杀死整个过程。操作系统知道如何清理进程中的资源,因此清理不是问题。不过,它仍然有其他潜在的问题:1(你几乎需要一个进程监视器来在需要时杀死进程,2(生成一个进程通常比仅仅创建一个套接字要昂贵得多。尽管如此,这可能是一个可行的选择,特别是如果:

  1. 您一次要处理少量连接
  2. 您通常对每个连接进行大量处理
  3. 只与本地主机打交道,因此您与它们的连接既快速又可靠
  4. 您更关心的是优化开发而不是执行

1.嗯,从技术上讲,这不是唯一可能的方法,但大多数替代方案都相对丑陋 - 更具体地说,我认为当您添加代码以找出存在问题然后解决问题时,您可能已经做了更多的额外工作,而不是只使用非阻塞套接字。