使用python进行socket编程时,遇到一个问题:
server.py:
>>> import socket
>>> s = socket.socket()
>>> s.bind(('', 12345))
>>> s.listen(5)
>>> s.accept()
client.py:
>>> import socket
>>> s = socket.socket()
>>> s.connect(('', 12345))
报错:
Traceback (most recent call last):
File "client.py", line 9, in <module>
s.connect((host, port))
File "<string>", line 1, in connect
socket.error: (10049, "Can't assign requested address")
google之,在zope讨论区http://zope.org/Collectors/Zope/1728找到一篇帖子,大意是说在windows平台下,socket所绑定的host名称是不可以指定为空字符串的。加个host的名字,问题消失了。将原帖转贴在这里:
Issue 1728 Transcript
= Resolve - Entry #7 by yuppie on May 16, 2005 3:19 pm
Status: Pending => Resolved
The months-old 2.8 Windows test failures are resolved, so I close this issue. I reopened http://www.zope.org/Collectors/Zope/1507 to track the related ip-address-setting-is-ignored issue.
This is the fix:
http://svn.zope.org/?view=rev&rev=30303
________________________________________
= Comment - Entry #6 by yuppie on May 8, 2005 12:50 pm
@ tim_one: Thanks for these infos. That would explain why ZConfig was changed. But I still believe it was wrong to hardcode a fix for this in ZConfig. Zope 2.7 doesn't have the same problems because it uses an older version of ZConfig.
I propose to discuss this on the related thread on zope-dev and zope3-dev because both products use ZConfig and have similar issues.
________________________________________
= Comment - Entry #5 by tim_one on May 8, 2005 12:25 pm
Well, it's "a Windows problem" because these tests only fail on Windows -- and they only fail in Zope 2.8, not in Zope 2.7; and they only started failing after someone "changed something" to fix Collector 1527 on Linux.
While it seems impossible to know for sure, I suspect the _underlying_ platform difference is that:
socket.connect((host, port))
on Windows blows up if an empty string is passed as `host`, but does not blow up on Linux in that case. For example, in one Python session do:
>>> import socket
>>> s = socket.socket()
>>> s.bind(('', 45454))
>>> s.listen(5)
>>> s.accept()
then in a distinct Python session do:
>>> import socket
>>> s = socket.socket()
>>> s.connect(('', 45454))
On Linux that works. On Windows the connect() attempt barfs like so:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<string>", line 1, in connect
socket.error: (10049, "Can't assign requested address")
I know that, in the past, there have been dozens (and dozens, and ...) of Zope and ZODB and ZRS tests that failed only on Windows because Linux-heads wrote connect() code passing an empty string for the host. So a "never pass an empty string for the host" meme got started. Perhaps it got applied too broadly here (it's fine to pass an empty string for `host` in a bind() call, where it acts like INADDR_ANY:
>>> socket.gethostbyname('')
'0.0.0.0'
on both Linux and Windows).
________________________________________
= Comment - Entry #4 by mhammond on May 8, 2005 8:22 am
I actually don't think this is a "windows" problem as such.
test_config.py says:
# On Linux the default hostname is an empty string, but on Windows
# it's "localhost". So factory.prepare() will replace factory.host
# with "127.0.0.1" only on non-Windows boxes.
In ZConfig.py, we can see code:
server = HTTPServer.zhttp_server(ip=self.host, ...)
[Note that 'self.ip' also exists, and appears to be the ip when run from the test suite - although self.host is passed for 'ip']
What I think is happening is that on Linux, we have a default IP (127.0.0.1) and no default hostname. On Windows, we have default IP *and* a default hostname ('localhost'). If the user overrides only one, things go wrong.
I expect that a Linux user could provoke the same error by (temporarily) making Linux default the host to 'localhost'. This would at least help people familiar with ZConfig but not Windows to reproduce the error environment.
I have no idea why Zope has a different config default for Windows - if there is an underying Windows issue that requires this, I can't see reference to it.
________________________________________
= Comment - Entry #3 by tim_one on Mar 29, 2005 10:24 am
Understood -- I'm not yelling at you <wink>, I just pointed to the old bug report because it has additional info I didn't want to bother copying over to this one.
ZC has some test machines set aside, but-- alas --no bandwidth so far to set up an automated test runner for Windows. It certainly sucks that test failures can persist for months without such a thing.
________________________________________
= Comment - Entry #2 by ajung on Mar 29, 2005 8:56 am
Yes, I closed the issue because I was not aware of any further problems on windows - especially not because we have no daily testrunner for Windows. (Un)fortunately I don't have a Windows
system here for further testing and debugging.
________________________________________
= Request - Entry #1 by tim_one on Mar 19, 2005 12:38 am
See
http://www.zope.org/Collectors/Zope/1507
for more info. That bug got closed without fixing the Windows problems. Most obvious is that these tests have been failing on Zope trunk since 14 October 2004. Here from current Zope trunk, WinXP Pro SP2, Python 2.3.5:
FAIL: test_http_factory (ZServer.tests.test_config.ZServerConfigurationTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:/Code/Zope/lib/python/ZServer/tests/test_config.py", line 110, in test_http_factory
self.assertEqual(server.ip, '127.0.0.1')
File "C:/Python23/lib/unittest.py", line 302, in failUnlessEqual
raise self.failureException, /
AssertionError: 'localhost' != '127.0.0.1'
======================================================================
FAIL: test_webdav_source_factory (ZServer.tests.test_config.ZServerConfigurationTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:/Code/Zope/lib/python/ZServer/tests/test_config.py", line 128, in test_webdav_source_factory
self.assertEqual(server.ip, '127.0.0.1')
File "C:/Python23/lib/unittest.py", line 302, in failUnlessEqual
raise self.failureException, /
AssertionError: 'localhost' != '127.0.0.1'