我正在尝试在 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_in
bind
sin_family
sin_addr
sin_port
sin_len
sin_zero