我想设置一个服务器/客户端,其中客户端通过套接字向服务器发送可序列化的对象。由于某种原因,当我尝试读取发送到服务器的对象时,我会不断得到java.net.SocketException: SocketClosed
。
这是我给客户的代码:
class Client(address: String, port: Int) {
private val connection: Socket = Socket(address, port)
private var connected: Boolean = true
private val writer = ObjectOutputStream(connection.getOutputStream())
private val reader = ObjectInputStream(connection.getInputStream())
init {
println("Connected to server at $address on port $port")
}
fun run() {
var sent = false
while (connected) {
try {
if (!sent) {
sent = true
writer.use {
it.writeObject("Hello")
it.flush()
}
println("Sent")
} else {
println("Didn't send")
}
Thread.sleep(1000)
} catch (ex: Exception) {
ex.printStackTrace()
shutdown()
}
}
}
...
}
这是服务器的代码:
class ClientHandler(private val client: Socket) {
private val reader = ObjectInputStream(client.getInputStream())
private val writer = ObjectOutputStream(client.getOutputStream())
private var running: Boolean = false
fun run() {
running = true
while (running) {
try {
reader.use {
val packet = it.readObject()
when (packet) {
is String -> {
println("Received packet with data: ${packet}")
}
}
}
} catch (ex: Exception) {
ex.printStackTrace()
shutdown()
}
}
}
...
}
我的服务器上的输出是
Server is running on port 9999
Client connected: 127.0.0.1
Received packet with data: Hello
java.net.SocketException: Socket closed
at java.base/java.net.SocketInputStream.socketRead0(Native Method)
at java.base/java.net.SocketInputStream.socketRead(SocketInputStream.java:115)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:168)
...
因此,好像我的String
的一个实例正在使用它,但是后来的调用声称该套接字已关闭。
我见过的与此问题相关的其他每篇文章都声称发件人(客户端)正在尽早关闭套接字。但是,我知道客户端不是通过自己的方式关闭套接字。如果我将客户代码更改为:
class Client(address: String, port: Int) {
...
private val writer = connection.getOutputStream() // Regular streams
private val reader = Scanner(connection.getInputStream())
...
fun run() {
var sent = false
while (connected) {
try {
if (!sent) {
sent = true
writer.write("Hello\n".toByteArray()) // Send regular byte array
println("Sent")
} else {
println("Didn't send")
}
...
}
和我的服务器代码:
class ClientHandler(private val client: Socket) {
private val reader = Scanner(client.getInputStream()) // Regular streams
private val writer = client.getOutputStream()
private var running: Boolean = false
fun run() {
running = true
while (running) {
try {
// Just read lines from stream
println(reader.nextLine())
}
...
}
然后我的输出就是我所期望的:
Server is running on port 9999
Client connected: 127.0.0.1
Hello
我唯一的假设是.readObject()
正在某种程度上关闭套接字连接,从而迫使下一个readObject()
抛出异常。不过,这对我来说没有太大意义。为什么会这样?
答案 0 :(得分:1)
深入研究代码可以给我所需的答案。 .use
似乎在完成后关闭了套接字。删除use { }
块使此工作按预期进行。