DataInputStream не получает данные после сброса DataOutputStream

Итак, я новичок в сокетах и ​​потоках данных ... И меня совершенно сбивает с толку эта проблема. Я часами искал решение, предполагая, что у других людей могла быть та же проблема, что и у меня, но пока я не нашел абсолютно ничего полезного.

Я пишу очень простую многопоточную серверную / клиентскую программу, которая должна открывать serverSocket и принимать соединения от клиентов, сохраняя их в простом массиве (я изменю процесс хранения, как только я действительно получу сообщения для отправки), и затем поток обработчика сообщений анализирует список и проверяет, написал ли пользователь на сервер. Если пользователь что-то написал, программа выводит полученное сообщение на консоль. Моя программа успешно записывает в серверный сокет через DataOutputStream, но когда я пытаюсь прочитать из соответствующего DataInputStream на стороне сервера, он сообщает, что поток пуст, и моя программа продолжит цикл. Я проверил, что DataOutputStream получает данные через DataOutputStream.size () и что DataInputStream, из которого я пытаюсь считать данные, соответствует правильному DataOutputStream, о котором я упоминал ранее.

Код пользователя:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;

public class User {
    private String hashID;
    private Socket connection;
    private static int hashVal = 0;
    DataInputStream consoleInputStream;
    String consoleInput = "";

    public User(Socket conn) throws SocketException {
        hashID = hashUserKey();
        connection = conn;
        connection.setSoTimeout(1500);
        consoleInputStream = new DataInputStream(System.in);
    }

    private static String hashUserKey() { //placeholder for now
        hashVal++;
        return("Guest" + hashVal);
    }

    public Socket getSocket() {
        return this.connection;
    }

    public String getID() {
        return this.hashID;
    }

    public boolean disconnect() {
        try {
            consoleInputStream.close();
            connection.close();
            return true;
        } catch (IOException e) {
            System.err.println(hashID + " was unable to successfully disconnect");
            return false;
        }
    }

    public void startConnection() {
        new Thread() {
            @Override
            public void run() {

                while(!connection.isClosed()) {

                    try {
                        consoleInput = consoleInputStream.readLine();
                        if (consoleInput != null || consoleInput != "") {
                            writeToServer(consoleInput);
                        }
                    } catch (IOException e) {
                        System.err.println("Was not able to read console input");
                    }
                }
                System.out.println("You were disconnected, have a nice day!");
                return;
            }
        }.start();

    }

    private boolean writeToServer(String toWrite) {
        try {
            String msg = hashID + ">>>: " + toWrite;
            DataOutputStream outStream = new DataOutputStream(connection.getOutputStream());
            outStream.writeUTF(toWrite + "\r\n");
            outStream.flush();
            consoleInput = "";
            System.out.println(msg + "\t was written to " + connection.getInetAddress() + ":" + connection.getPort());
            return true;
        } catch (IOException e) {
            System.err.println(hashID + " was unable to write to server");
            return false;
        }
    }

    @Override
    public boolean equals(Object o) {
        User t = (User) o;
        if (t.hashID == this.hashID) {
            return true;
        }
        return false;
    }

}

Код сервера:

import java.net.*;
import java.io.*;
import java.util.*;

public class TestServer {

        private static ServerSocket server;
        private static TestLogger logger;
        private static Thread serverHandlerThread;
        private static Thread messageHandlerThread;
        private static ArrayList<User> users;
        private static volatile boolean hasBeenStopped = false;

        public static boolean startServer(int port) {
            logger = new TestLogger();
            logger.log("Attempting to create default shutdown behavior for server");
            Runtime.getRuntime().addShutdownHook(new Thread() {
                    @Override
                    public void run() {
                        if (!hasBeenStopped) {
                            logger.warn("Server was shut down without running stopServer(), running by default");
                            stopServer();
                        }
                    }
                }
            );
            logger.log("Shutdown behaivor created. Now attempting to set up user database"/*TODO create a real database*/);
            users = new ArrayList<User>();
            logger.log("Attempting to start server");

            try {
                server = new ServerSocket(port);
                logger.log("Server successfully started at " + server.getInetAddress() + ":" + server.getLocalPort() +", now attempting to start user connection handler");
                serverHandlerThread = new Thread() {
                    @Override
                    public void run() {
                        this.setName("serverHandlerThread");
                        while(!server.isClosed()) {
                            try {
                                Socket temp = server.accept();
                                logger.log("Connection accepted from " + temp.getInetAddress());
                                System.out.println("Connection accepted from " + temp.getInetAddress());
                                startUserConnection(new User(temp));
                            } catch (SocketException e) {
                                logger.warn("Server was closed while in accept phase");
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                        logger.log(this.getName() + " was stopped, server socket was closed successfully");
                        return;
                    }
                };

                serverHandlerThread.start();
                logger.log("Server thread successfully started, listening for connections on: " + server.getInetAddress().toString() + ":" + port);

                logger.log("Attempting to start message handler thread to read user inputs");
                messageHandlerThread = new Thread() {
                    @Override
                    public void run() {
                        this.setName("messageHandlerThread");
                        while(!server.isClosed()) {
                            if (users.isEmpty()) {
                                continue;
                            }
                            for(int i = 0; i < users.size(); i++) {
                                User temp = users.get(i);
                                try {
                                    System.out.println(new DataInputStream(temp.getSocket().getInputStream()).readUTF());
                                } catch (IOException e) {
                                    System.err.println("Nothing to read from client: " + temp.getID());
                                }
                                try {
                                    Thread.sleep(2000);
                                } catch (InterruptedException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                };

                messageHandlerThread.start();
                return true;
            } catch (IOException e) {
                logger.error("Could not bind server socket to port.");
                return false;
            }

        }

        public static boolean stopServer() {
            logger.log("Started shut down process");
            if (serverHandlerThread == null || !serverHandlerThread.isAlive()) {
                logger.warn("Thread has not been started yet or has already been killed");
                return false;
            }
            else {
                stopAllUserConnections();

                try {
                    server.close();
                    hasBeenStopped = true;
                    while(serverHandlerThread.isAlive()) {

                    }
                    logger.log("Server was successfully shut down");
                    return true;
                } catch (IOException e) {
                    logger.error("Could not close server socket");
                    return false;
                }

            }
        }

        private static void startUserConnection(User user) {
            logger.log("Connected new user from " + user.getSocket().getInetAddress());
            users.add(user);
            System.out.println(user.getID() + " was added to list");
            user.startConnection();
        }

        private static boolean stopUserConnection(User user) {
            logger.log("Attempting to disconnect user, address: " + user.getSocket().getInetAddress());
            for(User u : users) {
                if (u.equals(user)) {
                    u.disconnect();
                    return true;
                }
            }
            logger.warn("Could not find user with address: " + user.getSocket().getInetAddress());
            return false;
        }

        private static boolean stopAllUserConnections() {
            logger.log("Attempting to disconnect all users from the server");
            if (users.isEmpty()) {
                logger.warn("No users available to disconnect");
                return false;
            }
            for(User u : users) {
                u.disconnect();
            }
            users.clear();
            return true;
        }

        public static void main(String args[]) {
            startServer(*the_port*);
            Client c = new Client();
            c.connect("0.0.0.0", *the_port*);
        }
}

Код клиента:

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {

    public boolean connect(String serverName, int port) {
        try {
            System.out.println("Attempting to connect");
            Socket sock = new Socket(serverName, port);
            System.out.println("Connected");
            return true;
        } catch (UnknownHostException e) {
            System.err.println("Could not resolve " + serverName + ":" + port);
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }
}

Итак, как я сказал выше, это работает нормально до тех пор, пока я не попытаюсь прочитать данные, записанные на сервер. Независимо от того, что я делаю, серверный вызов readUTF () в сокете всегда вызывает исключение IOException, а проверка байтов, готовых к чтению, с помощью DataInputStream.available () также возвращает 0. Мой пример вывода из моего последнего прогона выглядит следующим образом:

Attempting to connect
Connected
Connection accepted from *the_address*
Guest1 was added to list
Nothing to read from client: Guest1
Nothing to read from client: Guest1
Nothing to read from client: Guest1
test
Guest1>>>: test  was written to *the_address:another_port*
Nothing to read from client: Guest1
Nothing to read from client: Guest1
Nothing to read from client: Guest1

Я знаю, что мой код может быть ужасно оптимизирован, и я буду работать над исправлением этого позже, но сейчас все, что я хочу знать, это почему мой DataInputStream пуст после сброса соответствующего DataOutputStream, и как я могу успешно отправлять данные UTF между ними. .

Вы пробовали Socket.setTcpNoDelay(true); на своих клиентских сокетах?

Alirus 18.12.2018 22:05

Я только что попробовал. К сожалению, без разницы ...

LotsOfHelpNeeded 18.12.2018 22:14
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
75
0

Другие вопросы по теме