ObjectInputStream readObject意外关闭套接字

问题描述 投票:-1回答:1

我想设置服务器/客户端,其中客户端通过套接字向服务器发送可序列化的对象。出于某种原因,当我尝试读取发送到服务器的对象时,我会一直显示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()引发异常。不过,这对我来说并没有太大意义。为什么会发生?

sockets kotlin network-programming serversocket
1个回答
1
投票

深入研究代码给了我所需的答案。似乎.use完成后将其关闭。卸下use { }块可使此工作按预期进行。

© www.soinside.com 2019 - 2024. All rights reserved.