Я пытаюсь настроить простой веб-сервер в Mac OS X, но при запуске постоянно получаю сообщение об ошибке 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
Это не совсем ответ, поскольку он не решает напрямую вашу проблему ... но похоже, что ваша проблема связана с лукавством. То есть в моей системе OS X 10.6 у меня такая же проблема, как и при использовании кода хитрости из вашего примера. С другой стороны, отлично работает следующее:
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.
В самом деле, в моем случае проблема связана с неинициализированными полями в структуре, которые не имеют ничего общего с семантическим адресом сокета.
Я добавил memset(&sa, 0, sizeof sa)
и теперь это связывает.
Почти наверняка реализация Guile столкнулась с той же проблемой: инициализация только задокументированных полей struct sockaddr_in
. В любом случае симптомы были точно такие же: INADDR_ANY
обязательный, но INADDR_LOOPBACK
отказ с тем же errno
.
Изменить: извините, если я не понимаю; Я имею в виду то, что я добавил к вопросу, который кто-то удалил. А именно, я столкнулся с точно такой же проблемой при реализации (по чистой случайности) другого диалекта Лиспа. Я добавил свои наблюдения, а также некоторые gdb
трассировки сеанса отладки, показывающие содержимое struct sockaddr_in
перед bind
вызов. Адрес правильно инициализирован sin_family
, sin_addr
и sin_port
поля. Однако sin_len
поле во главе структуры (присутствует на Дарвине, отсутствует на других платформах) не инициализировано, а также sin_zero
массив заполнения в конце.