Accepting a socket on Windows 7 takes more than a second
Here's what I've done:
- I wrote a minimal web server (using Qt, but I don't think it's relevant here).
- I'm running it on a legal Windows 7 32-bit.
The problem:
- If I make a request with Firefox, IE, Chrome or Safari it takes takes about one second before my server sees that there is a ne开发者_如何学JAVAw connection to be accepted.
Clues:
- Using other clients (wget, own test client that just opens a socket) than Firefox, IE, Chrome, Safari seeing the new connection is matter of milliseconds.
- I installed Apache and tried the clients mentioned above. Serving the request takes ~50ms as expected.
- The problem isn't reproducible when running Windows XP (or compiling and running the same code under Linux)
- The problem seems to present itself only when connecting to localhost. A friend connected over the Internet and serving the connection was a matter of milliseconds.
- Running the server in different ports has no effect on the 1 second latency
Here's what I've tried without luck:
- Stopped the Windows Defender service
- Stopped the Windows Firewall service
Any ideas? Is this some clever 'security feature' in Windows 7? Why isn't Apache affected? Why are only the browsers affected?
If you're saying "localhost" instead of "127.0.0.1", you're forcing a name lookup before the actual connection attempt, adding delay.
In addition, some browsers, like Firefox 3.5+, don't use the operating system's DNS lookup mechanism, which is why it can have different performance than, say, wget.
You may be running into some automatic proxy discovery problem. In Firefox, you can disable this in Options | Advanced | Network | Settings; select either "No proxy" or give it explicit values. There's also the Internet Properties control panel, which is IE's network settings, but other browsers on Windows may obey settings here, too. Again, disable auto-proxy discovery. This can speed connections outside localhost, too.
For some reason Windows 7 takes 1 second to resolve address localhost regardless of it being in hosts file.
Adding localhost1 to hosts file and using that works around the problem.
When connecting to localhost
on a IPv4/IPv6 dual stack host:
- A DNS lookup is performed for
localhost
. - The DNS server (whether IPv6 enabled or not - this doesn't matter) returns both the
AAAA
record::1
, and theA
record127.0.0.1
. - The client first attempts to connect to
::1
. - We assume your server program is not IPv6-capable, which is a common case - due to historical reasons, many servers bind their socket to
0.0.0.0
by default rather than[::]
. - Here an
ECONNREFUSED
error would be raised for the client. This happens immediately on most platforms; on Windows however, a single call toconnect()
would try 3 times in 500ms intervals before giving up, hence taking a bit more than one second (See http://stackoverflow.com/q/19440364 for more details). - The client then creates a connection to
127.0.0.1
instead.
This would explain all your clues above:
- If you make a request with Firefox, IE, Chrome, Safari or any other IPv6-capable clients, it takes takes about one second trying for
::1
before connecting to127.0.0.1
. - Your own test client just opens a
INET
socket, so it won't try::1
at all. - Using a dual-stack server such as Apache, the clients will connect to
::1
happily. - The problem isn't reproducible on Windows XP, of which IPv6 support is not enabled by default.
- The problem seems to present itself only when connecting to
localhost
, as your friend connected with an IPv4-only network. - Running the server in different ports has no effect on the 1 second latency.
精彩评论