为什么我无法在 Mac OS X 上绑定到 127.0.0.1?

为什么我无法在 Mac OS X 上绑定到 127.0.0.1?

我正在尝试在 Mac OS X 上设置一个简单的 Web 服务器,但运行时总是出错bind。以下是我正在运行的内容(此记录使用 GNU Guile,但只是作为 posix 的便捷接口)。

(define addr (inet-aton "127.0.0.1"))                     ; get internal representation of 127.0.0.1
(define sockaddr (make-socket-address AF_INET addr 8080)) ; make a struct sockaddr
(define sock (socket PF_INET SOCK_STREAM 0))              ; make a socket
(bind sock sockaddr)                                      ; bind the socket to the address

这给了我错误In procedure bind: can't assign requested address

所以我再次尝试任何地址。

(define anyaddr (make-socket-address AF_INET INADDR_ANY 8080)) ; allow any address
(bind sock anyaddr)

一切正常。但很奇怪,ifconfig lo0因为

lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
  inet6 ::1 prefixlen 128 
  inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 
  inet 127.0.0.1 netmask 0xff000000 

因此,环回设备已分配给127.0.0.1。所以我的问题是,为什么我不能绑定到该地址?

谢谢。

更新:的输出route get 127.0.0.1

   route to: localhost
destination: localhost
  interface: lo0
      flags: <UP,HOST,DONE,LOCAL>
 recvpipe  sendpipe  ssthresh  rtt,msec    rttvar  hopcount      mtu     expire
   49152     49152         0         0         0         0     16384         0 

答案1

这不完全是一个答案,因为它不能直接解决你的问题……但看起来你的问题似乎与 guile 有关。也就是说,在我的 OS X 10.6 系统上,我使用示例中的 guile 代码遇到了与你相同的问题。另一方面,下面的方法可以正常工作:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('127.0.0.1', 8080))
s.listen(5)

c, addr = s.accept()
c.send('hello\n')
c.close()

如果我运行此代码,我可以看到套接字正在监听:

netstat -f inet -an | grep 8080
tcp4       0      0  127.0.0.1.8080         *.*                    LISTEN

连接到端口 8080 将会执行你所期望的操作:

$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello
Connection closed by foreign host.

答案2

事实上,就我而言,问题在于结构中未初始化的字段,它们与语义套接字地址无关。

我添加了一个memset(&sa, 0, sizeof sa)并且现在它绑定了。

几乎可以肯定,Guile 实现遇到了同样的问题:仅初始化 的已记录字段struct sockaddr_in。无论如何,症状完全相同:INADDR_ANY绑定,但INADDR_LOOPBACK拒绝相同的errno

编辑:如果我不清楚,请见谅;我指的是我添加到问题中但被某人删除的内容。也就是说,我在实现另一种 Lisp 方言时(纯属巧合)遇到了完全相同的问题。我添加了我的观察结果,以及一些调试会话跟踪,显示了调用之前gdb的内容。地址显示正确初始化了和字段。但是,结构头部的字段(在 Darwin 上存在,在其他平台上不存在)未初始化,末尾的填充数组也未初始化。struct sockaddr_inbindsin_familysin_addrsin_portsin_lensin_zero

相关内容