Sockets ObjectInputStream readObject意外关闭套接字

Sockets ObjectInputStream readObject意外关闭套接字,sockets,kotlin,network-programming,serversocket,Sockets,Kotlin,Network Programming,Serversocket,我想设置一个服务器/客户机,其中客户机通过套接字向服务器发送一个可序列化对象。出于某种原因,当我试图读取发送到服务器的对象时,我一直得到java.net.SocketException:SocketClosed 以下是我的客户代码: class Client(address: String, port: Int) { private val connection: Socket = Socket(address, port) private var connected: Bool

我想设置一个服务器/客户机,其中客户机通过套接字向服务器发送一个可序列化对象。出于某种原因,当我试图读取发送到服务器的对象时,我一直得到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)
...
因此,似乎我的字符串的一个实例正在穿越,但后来的调用声称套接字已关闭

我看到的每一篇与此问题相关的帖子都声称发送方客户端提前关闭了套接字。但是,我知道客户端并不是通过自己的方式关闭套接字。如果我将客户端代码更改为:

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抛出异常。不过,这对我来说意义不大。为什么会发生这种情况?

在代码中再翻一翻,我得到了需要的答案。看起来像。使用完成后关闭插座。删除use{}块使这项工作如期进行。

这是因为当指定的代码块完成时,use方法关闭了流。这是。