8

我在 Windows 7 中运行了两个 stunnel 实例,配置为侦听同一端口,并且似乎它们都成功地侦听了同一端口(仅使用 socket()/bind()/listen())。这两个实例似乎都成功调用了所有调用,并且它们显示在 netstat 中:

C:\>netstat -ano | grep 8000
  TCP    0.0.0.0:8000           0.0.0.0:0              LISTENING       5828
  TCP    0.0.0.0:8000           0.0.0.0:0              LISTENING       5852

第一个监听的会获取所有传入的请求。

这与我的所有期望完全相反。(我期待 EADDRINUSE 告诉我端口很忙。)所以....

  1. 为什么/这是如何工作的?这种行为在某些情况下有用吗?
  2. 如果另一个应用程序要捕获传入的请求,我不希望实例成功运行...如何使端口独占?
4

1 回答 1

7

这可以通过使用SO_REUSEADDR标志打开套接字来完成,这对于 TCP 套接字应用程序并不少见。

通常,SO_REUSEADDR 用于以下两种情况之一:

  1. 当一个进程在没有机会关闭其套接字的情况下崩溃、被杀死或强制重新启动时。或者进程退出但socket(或子连接socket)仍处于FIN_WAIT或FIN_WAIT2状态。第二个进程可以打开套接字而不会得到“已经在使用”的错误代码。我已经阅读了一些关于 SO 的帖子,表明这是 TCP 套接字的最佳实践。

  2. 同一个服务器程序要么分叉,要么同时运行多次。这允许负载平衡,而无需编写服务器程序以使用线程。通常,侦听套接字的程序的“其他实例”将接受传入连接,而第一个实例正忙于另一个连接。

关于你的第二个问题,最简单的方法是不要使用 SO_REUSEADDR。如果您担心可能有恶意应用尝试使用 SO_REUSADDR,那么您的应用可以使用 SO_EXCLUSIVEADDRUSE。(一个标志,基本上说,“不允许其他应用程序使用 SO_REUSEADDR 打开同一个端口。)

于 2012-09-10T15:48:41.873 回答