我正在尝试使用Aleph在Clojure中设置服务器发送的事件,但它不能通过 IPv4 工作。如果我通过 IPv6 连接,一切都很好。这发生在 Linux 和 MacOS 上。我有一个完整的例子来说明我在 GitHub 上谈论的内容。
我不认为我在做任何特别花哨的事情。整个代码都在 GitHub 上,但基本上我的程序是:
(def my-channel (permanent-channel))
(defroutes app-routes
(GET "/events" []
{:headers {"Content-Type" "text/event-stream"}
:body my-channel}))
(def app
(handler/site app-routes))
(start-server (wrap-ring-handler app) {:port 3000}))
但是,当我连接到时127.0.0.1:3000
,我可以看到 curl 发送请求标头,但它只是挂起,从不打印响应标头:
$ curl -vvv http://127.0.0.1:3000/events
* About to connect() to 127.0.0.1 port 3000 (#0)
* Trying 127.0.0.1...
* Adding handle: conn: 0x7f920a004400
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7f920a004400) send_pipe: 1, recv_pipe: 0
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
> GET /events HTTP/1.1
> User-Agent: curl/7.30.0
> Host: 127.0.0.1:3000
> Accept: */*
如果我通过 IPv6 连接,响应会立即出现,并且我enqueue
在通道中的事件会正确发送:
$ curl -vvv http://localhost:3000/events
* Adding handle: conn: 0x7f943c001a00
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7f943c001a00) send_pipe: 1, recv_pipe: 0
* About to connect() to localhost port 3000 (#0)
* Trying ::1...
* Connected to localhost (::1) port 3000 (#0)
> GET /events HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:3000
> Accept: */*
>
< HTTP/1.1 200 OK
* Server aleph/0.3.0 is not blacklisted
< Server: aleph/0.3.0
< Date: Tue, 15 Apr 2014 12:27:05 GMT
< Connection: keep-alive
< Content-Type: text/event-stream
< Transfer-Encoding: chunked
我也在 Chrome 中重现了这种行为。在 IPv4 和 IPv6 情况下,tcpdump
都表明响应标头通过网络传输。
这种行为发生在lein run
uberjar 和 uberjar 中。如果我使用-Djava.net.preferIPv4Stack=true
.
如何让我的应用程序在 IPv4 上的行为与在 IPv6 上的行为相同?