ObjectInputStream readObject неожиданно закрывает сокет - PullRequest
0 голосов
/ 28 сентября 2019

Я хочу настроить сервер / клиент, где клиент отправляет сериализуемый объект через сокет на сервер.По какой-то причине я продолжаю получать 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

MyЕдинственная гипотеза состоит в том, что .readObject() как-то закрывает соединение с сокетом, заставляя следующее readObject() вызвать исключение.Это не имеет большого смысла для меня, хотя.Почему это случилось?

1 Ответ

0 голосов
/ 28 сентября 2019

Копаться в коде, чтобы узнать больше, дало мне ответ, который мне был нужен.Похоже, .use закрывает сокет после его завершения.Удаление блоков use { } сделало эту работу ожидаемой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...