
我將要描述的問題僅在執行一些 Java 單元測試時才會出現。不過,我很確定原因是 OS-X 配置,而不是 Java,所以我將帖子發布給超級用戶而不是 StackOverflow。
我們有一個 Java 單元測試,它啟動一個嵌入式伺服器,然後向 at 發出請求http://localhost:9324
。在我升級到 Yosemite 之前,這些測試曾經通過,但現在卻失敗了。具體症狀和我嘗試過的事情:
解析為 AWDL 介面
我查看了 netstat 來查看連接埠 9324 的存取情況。
localhost:platform oliver$ netstat -tn | grep 9324
tcp6 0 0 fe80::b8d2:8eff:.50602 fe80::b8d2:8eff:.9324 SYN_SENT
因此由於某種原因 localhost 解析為 IPV6 位址並ifconfig
顯示它是awdl0
.谷歌搜尋一下就會發現,這是蘋果用於點對點共享的介面。請注意nslookup localhost
,dig localhost
和都按預期dscacheutil -q host -a name localhost
返回。127.0.0.1
所以,不知何故,Java 程式碼以不同的方式進行名稱解析或其他操作(所以是的,也許這是一個 Java 問題)?
解析為外部位址
透過關閉 AWDL 介面sudo ifconfig awdl0 down
會導致程式碼停止掛起,並且 netstat 報告基本正確的資訊:
tcp4 0 0 192.168.0.124.52137 192.168.0.124.9324 SYN_SENT
tcp4 0 0 127.0.0.1.9324 127.0.0.1.52135 ESTABLISHED
tcp4 0 0 127.0.0.1.52135 127.0.0.1.9324 ESTABLISHED
但請注意,由於某種原因,使用localhost
地址的本地代碼正在命中192.168.0.124
,我的外部的IP 位址,並且該代碼被卡住SYN_SENT
並且將掛起並且永遠不會得到回應。請注意,這不是由於防火牆設定造成的,因為我在此測試中完全停用了防火牆。
連線被拒絕
儘管外部位址的使用很奇怪,但有一些看起來正確的連接似乎使用了環回,但它們ConnectionRefused
從 Java 中得到了錯誤。但是,curl http://localhost:9324
連接成功並得到回應。
問題
我很困惑。這可能是 Java 問題,但我懷疑我的 OS-X 網路設定不知何故被破壞了。
哦,這是我的 /etc/resolv.conf:
#
# Mac OS X Notice
#
# This file is not used by the host name and address resolution
# or the DNS query routing mechanisms used by most processes on
# this Mac OS X system.
#
# This file is automatically generated.
#
nameserver 10.1.10.1
nameserver 2001:558:feed::1
nameserver 2001:558:feed::2
我的 /private/etc/resolv.conf 是相同的。
/etc/hosts 是:
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost
這是輸出ifconfig -a
:
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
options=3<RXCSUM,TXCSUM>
inet6 ::1 prefixlen 128
inet 127.0.0.1 netmask 0xff000000
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
nd6 options=1<PERFORMNUD>
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
stf0: flags=0<> mtu 1280
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
ether 3c:15:c2:da:29:0c
nd6 options=1<PERFORMNUD>
media: autoselect (<unknown type>)
status: inactive
en1: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
options=60<TSO4,TSO6>
ether 72:00:04:0f:34:70
media: autoselect <full-duplex>
status: inactive
en2: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
options=60<TSO4,TSO6>
ether 72:00:04:0f:34:71
media: autoselect <full-duplex>
status: inactive
p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304
ether 0e:15:c2:da:29:0c
media: autoselect
status: inactive
awdl0: flags=8902<BROADCAST,PROMISC,SIMPLEX,MULTICAST> mtu 1452
ether ba:d2:8e:05:03:6c
nd6 options=1<PERFORMNUD>
media: autoselect
status: inactive
bridge0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=63<RXCSUM,TXCSUM,TSO4,TSO6>
ether 3e:15:c2:ad:9e:00
Configuration:
id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0
maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200
root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0
ipfilter disabled flags 0x2
member: en1 flags=3<LEARNING,DISCOVER>
ifmaxaddr 0 port 5 priority 0 path cost 0
member: en2 flags=3<LEARNING,DISCOVER>
ifmaxaddr 0 port 6 priority 0 path cost 0
nd6 options=1<PERFORMNUD>
media: <unknown type>
status: inactive
en5: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=23<RXCSUM,TXCSUM,TSO4>
ether 00:24:9b:0f:3c:02
inet6 fe80::224:9bff:fe0f:3c02%en5 prefixlen 64 scopeid 0xc
inet 192.168.0.50 netmask 0xffffff00 broadcast 192.168.0.255
inet6 2601:1c0:c901:980e:224:9bff:fe0f:3c02 prefixlen 64 autoconf
inet6 2601:1c0:c901:980e:4041:88e9:46e8:a893 prefixlen 64 autoconf temporary
nd6 options=1<PERFORMNUD>
media: autoselect (1000baseT <full-duplex,flow-control,energy-efficient-ethernet>)
status: active
答案1
歡迎來到後 IPv4 世界。當您使用 nslookup 或 dig 等實用程式時,預設會傳回「A」記錄。然而,對於支援現代 IPv6 的作業系統和應用程序,他們通常會先檢查「AAAA」記錄,以查看該資源是否可透過 IPv6 使用,然後再求助於 IPv4 資源。
所以發生的情況是,您同時擁有 IPv4 條目和 IPv6 條目本機在您的系統上,它幾乎總是首選 IPv6。
那麼,你能對此做些什麼呢?嗯,你有幾個選擇。您可以刪除 IPv6 條目本機或完全停用 IPv6,但這不是一個理想的解決方案,實際上是「向後看」而不是向前邁進。
相反,您可能應該確保您的服務配置為除了 IPv4 之外還可以在 IPv6 上運行。您可能還需要對 IPv6 防火牆規則進行一些調整才能允許該服務。這可以讓您為未來 IPv6 取代 IPv4 成為主流協定做好準備。
答案2
嘗試重置discoveryd
或刷新其緩存,或恢復到 mDNSResponder(Yosemite 之前的 DNS 解析器)。
以下是刷新快取的方法discoveryd
:
sudo discoveryutil mdnsflushcache
恢復到 mDNSResponder 的描述如下: