gpt4 book ai didi

java - Java 中非常奇怪的套接字行为;不总是关闭端口?

转载 作者:搜寻专家 更新时间:2023-10-31 19:56:57 27 4
gpt4 key购买 nike

在一个非常大的项目的开发过程中,我们积累了大量的单元测试。许多这样的测试启动服务器、连接到这些服务器并关闭服务器和客户端,通常在同一个过程中。

但是,这些测试随机失败并显示“无法绑定(bind)地址 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
))
)

异常随机出现在我们启动第二个服务器的那一行。看起来 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
)))
)

我还注意到 10 毫秒甚至 100 毫秒的 sleep 时间并不能解决问题。然而,1000 毫秒(到目前为止)设法阻止了它。

编辑 2:有人让我进入 SO_LINGER - 但我找不到在 ServerSockets 上设置它的方法。有人对此有任何想法吗?

编辑 3:原来 SO_LINGER 默认是禁用的。我们还能看什么?

更新:问题的大部分已经解决,在 10,000 个左右的端口范围内使用动态端口分配。不过,我还是想看看人们能想出什么。

最佳答案

我(不太)了解 Clojure 语法,但您应该调用 socket.setReuseAddr(true) .这允许程序重用端口,即使可能有套接字处于 TIME_WAIT 状态。

关于java - Java 中非常奇怪的套接字行为;不总是关闭端口?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12144052/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com