gdu*_*002 5 java sockets clojure
在一个大型项目的开发过程中,我们已经积累了大量的单元测试.许多这些测试通常在同一个进程中启动服务器,连接到这些服务器并关闭服务器和客户端.
但是,这些测试随机失败,并显示"无法绑定地址127.0.0.1 :( port)".重新运行测试时,错误通常会消失.
现在,我们认为这是我们测试的问题,但我们决定在Clojure中编写一个小测试,我将在下面发布(并评论非Clojure人员).
(ns test
(:import [java.net Socket ServerSocket]))
(dotimes [n 10000] ; Run the test ten thousand times
(let [server (ServerSocket. 10000) ; Start a server on port 10000
client (Socket. "localhost" 10000) ; Start a client on port 10000
p (.getLocalPort client)] ; Get the local port of the client
(.close client) ; Close the client
(.close server) ; Close the server
(println "n = " n) ; Debug
(println "p = " p) ; Debug
(println "client = " client) ; Debug
(println "server = " server) ; Debug
(let [server (ServerSocket. p)] ; Start a server on the local port of the client we just closed
(.close server) ; Close the server
(println "client = " client) ; Debug
(println "server = " server) ; Debug
))
)
Run Code Online (Sandbox Code Playgroud)
在我们启动第二台服务器的行上随机出现该异常.似乎Java正在保留本地端口 - 即使该端口上的客户端已经关闭.
所以,我的问题:为什么Java真的这样做,为什么它看似随机?
编辑:有人建议我将套接字的reuseAddr设置为true.我做到了这一点,没有任何改变,所以这是下面的代码.
(ns test
(:import [java.net Socket ServerSocket InetSocketAddress]))
(dotimes [n 10000] ; Run the test ten thousand times
(let [server (ServerSocket. )] ; Create a server socket
(. server (setReuseAddress true)) ; Set the socket to reuse address
(. server (bind (InetSocketAddress. 10000))) ; Bind the socket
(let [client (Socket. "localhost" 10000) ; Start a client on port 10000
p (.getLocalPort client)] ; Get the client's local port
(.close client) ; Close the client
(.close server) ; Close the server
; (. Thread (sleep 1000)) ; A sleep for testing
(println "n = " n) ; Debug
(println "p = " p) ; Debug
(println "client = " client) ; Debug
(println "server = " server) ; Debug
(let [server (ServerSocket. )] ; Create a server socket
(. server (setReuseAddress true)) ; Set the socket to reuse address
(. server (bind (InetSocketAddress. p))) ; Bind the socket to the local port of the client we just had
(.close server) ; Close the server
(println "client = " client) ; Debug
(println "server = " server) ; Debug
)))
)
Run Code Online (Sandbox Code Playgroud)
我还注意到10毫秒甚至100毫秒的睡眠并不能解决这个问题.然而,1000毫秒(到目前为止)已设法阻止它.
编辑2:有人把我放到了SO_LINGER上 - 但我找不到在ServerSockets上设置它的方法.有人有任何想法吗?
编辑3:默认情况下,SO_LINGER被禁用.我们还能看到什么?
更新:问题已经解决了大部分,使用10,000个左右端口的动态端口分配.但是,我仍然希望看到人们可以想出什么.
| 归档时间: |
|
| 查看次数: |
1001 次 |
| 最近记录: |