web-dev-qa-db-ja.com

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が発生します。

だから私はanyアドレスを許可してもう一度試しました。

(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 
2
Noah Lavine

それはあなたの問題を直接解決しないので、これは正確な答えではありません...しかし、あなたの問題はギールに特有であるように見えます。つまり、私の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
larsks

実際、私の場合、問題は、セマンティックソケットアドレスとは関係のない構造内の初期化されていないフィールドにあります。

memset(&sa, 0, sizeof sa)を追加したところ、バインドされました。

Guileの実装で同じ問題が発生したのはほぼ確実です。つまり、struct sockaddr_inの文書化されたフィールドのみを初期化します。いずれの場合も、症状はまったく同じでした。INADDR_ANYバインディングですが、INADDR_LOOPBACKは同じerrnoで拒否します。

編集:不明な点がある場合は申し訳ありません。誰かが削除した質問に追加したものを指します。つまり、私は(まったくの偶然によって)別のLISP方言の実装でまったく同じ問題に遭遇しました。 gdb呼び出しの前にstruct sockaddr_inの内容を示すいくつかのbindデバッグセッショントレースとともに、観察結果を追加しました。アドレスは、正しく初期化されたsin_familysin_addr、およびsin_portフィールドを示しました。ただし、構造の先頭にあるsin_lenフィールド(Darwinに存在し、他のプラットフォームには存在しない)は初期化されておらず、最後にsin_zeroパディング配列があります。

0
Kaz