为什么Socket.connect的失败尝试在Windows上花费1秒?

时间:2013-10-18 02:00:21

标签: windows tcp connection

使用.net,我注意到尝试连接到未侦听的端口总是需要1秒钟。要检查这是否是.net抽象中的问题,或者它是否是一个较低级别的问题,并将其与linux进行比较(其中一个不成功的telnet需要3ms),我使用了node.js脚本来连接到端口

  • 12345,没有进程正在侦听的端口
  • 80,正在收听的端口

Windows 的结果:

Connecting to 127.0.0.1:12345
#3: error elapsed: 1000ms, Error: connect ECONNREFUSED
#2: error elapsed: 1002ms, Error: connect ECONNREFUSED
#4: error elapsed: 1003ms, Error: connect ECONNREFUSED
#1: error elapsed: 1007ms, Error: connect ECONNREFUSED
#0: error elapsed: 1015ms, Error: connect ECONNREFUSED

Connecting to 127.0.0.1:80
#0: connect elapsed: 8ms
#1: connect elapsed: 1ms
#2: connect elapsed: 3ms
#3: connect elapsed: 4ms
#4: connect elapsed: 6ms

Linux 的结果:

Connecting to 127.0.0.1:12345
#4: error elapsed: 0ms, Error: connect ECONNREFUSED
#3: error elapsed: 1ms, Error: connect ECONNREFUSED
#2: error elapsed: 1ms, Error: connect ECONNREFUSED
#1: error elapsed: 1ms, Error: connect ECONNREFUSED
#0: error elapsed: 3ms, Error: connect ECONNREFUSED

Connecting to 127.0.0.1:80
#4: connect elapsed: 0ms
#3: connect elapsed: 0ms
#2: connect elapsed: 0ms
#1: connect elapsed: 1ms
#0: connect elapsed: 2ms

Node.js 来源

var net = require('net');
var host = process.argv[2];
var port = Number(process.argv[3]);
console.log("Connecting to %s:%d", host, port);
for (i = 0; i < 5; i++)
{
  (function(i) {
    var date = +new Date;
    var client = net.connect({host: host, port: port});
    client.on('error', function(msg)
    {
      console.log("#%d: error elapsed: %dms, %s", i, new Date - date, msg);
    });
    client.on('connect', function()
    {
      console.log("#%d: connect elapsed: %dms", i, new Date - date);
    });
  })(i);
}

几个笔记

  • 我也试过远程IP地址,结果与上面显示的localhost
  • 类似
  • 在node.js的情况下和我编写它的方式中,(异步)连接尝试并行运行,但是在.net的情况下,我正在同步测试,即一次尝试​​接着另一次,结果是相同:每次1秒

知道为什么Windows在这里很慢?这是某种刻意的扼杀吗?

2 个答案:

答案 0 :(得分:2)

@ HarryJohnston的评论让我重写了程序以查看

  

如果另一个程序在一秒延迟期间开始侦听该端口会发生什么

似乎,在Windows上,对connect()的调用尝试以500毫秒的间隔连接到未绑定的端口最多3次。如果第三次尝试也失败了,它就会放弃。

以下是测试运行的日志,我偶尔会随机启动并停止侦听端口12345的进程:

Connecting to 192.168.77.11:12345
#1: error elapsed: 1008ms, Error: connect ECONNREFUSED
#2: error elapsed: 1001ms, Error: connect ECONNREFUSED
#3: error elapsed: 1004ms, Error: connect ECONNREFUSED
#4: connect elapsed: 1001ms
#5: connect elapsed: 1000ms
#6: connect elapsed: 500ms
#7: error elapsed: 1000ms, Error: connect ECONNREFUSED
#8: connect elapsed: 1001ms
#9: error elapsed: 1000ms, Error: connect ECONNREFUSED
#10: connect elapsed: 500ms
#11: error elapsed: 1000ms, Error: connect ECONNREFUSED
#12: error elapsed: 1000ms, Error: connect ECONNREFUSED
#13: connect elapsed: 500ms
#14: error elapsed: 1000ms, Error: connect ECONNREFUSED
#15: connect elapsed: 500ms
#16: error elapsed: 1000ms, Error: connect ECONNREFUSED
#17: connect elapsed: 500ms
#18: connect elapsed: 1000ms
#19: connect elapsed: 1000ms
#20: connect elapsed: 500ms
#21: connect elapsed: 1011ms
#22: connect elapsed: 1000ms
#23: error elapsed: 1000ms, Error: connect ECONNREFUSED

修改后的源代码:

var net = require('net');
var host = process.argv[2];
var port = Number(process.argv[3]);
console.log("Connecting to %s:%d", host, port);
var connect = function(i) {
    var date = +new Date;
    var client = net.connect({host: host, port: port});
    client.on('error', function(msg)
    {
      console.log("#%d: error elapsed: %dms, %s", i, new Date - date, msg);
      connect(i + 1);
    });
    client.on('connect', function()
    {
      console.log("#%d: connect elapsed: %dms", i, new Date - date);
      connect(i + 1);
    });
  };
connect(1);

答案 1 :(得分:1)

根据this article by Microsoft,原因是RFC留给实现来决定何时拒绝连接时要做什么,而在Windows上,默认值是在失败前重试3次。