Java: потеря данных через сокет TCP - PullRequest
0 голосов
/ 24 января 2019

Я пытаюсь создать Сервер (и, конечно, Клиента) для моей Игры.Он разработан с Java и не требует дополнительных библиотек или внешней работы.Соединение между клиентом и сервером в данный момент настроено так, что оно посылает определенное количество байтов (512) в виде «пакетов».Каждый пакет имеет идентификатор для своего типа (1 байт) и тело для своих данных (511 байт).В целом эта связь, кажется, работает.Проблема, с которой я сейчас сталкиваюсь, заключается в том, что когда я отправляю большое количество данных (карта ~ 10kb ~ 1300 пакетов) как можно быстрее, я, похоже, теряю сообщения или получаю сообщения с ошибкой (например, неправильный идентификатор пакета)).Я не могу понять, почему это происходит.Насколько я понимаю, сокеты в Java используют протокол TCP, который, насколько я знаю, должен предотвратить эти проблемы.

Это важная (на мой взгляд) часть сервера:

void sendToClient(Queue<DataPackage> packages) {
    if(isConnected()){
        try {
            while(!packages.isEmpty()){
                this.out.write(packages.get().getByteData());
                packages.remove();
                this.out.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
            if(!isConnected()){
                if(!ended){
                    ended = true;
                    server.getServerManager().getEventManager().publishServerEvent(new ServerLostConnectionToClientEvent(id, connection));
                }
            }
        }
    }
}

Это важная (на мой взгляд) часть клиента:

private void acceptData() throws UnsupportedPackageException {
    byte[] income = new byte[DataPackage.MAXPACKAGELENGTH];
    try {
        for(int length = in.read(income); length!=-1 && isConnected(); length = in.read(income)){
            income = Arrays.copyOf(income, DataPackage.MAXPACKAGELENGTH);   

            DataPackage dataPackage = null;
            try {
                dataPackage = new DataPackage(income, length);
            } catch (Exception ea) {ea.printStackTrace();}

            if(dataPackage!=null){

                if(!this.dataStreams.containsKey(dataPackage.getId())) this.dataStreams.put(dataPackage.getId(), new Queue<DataPackage>());
                Queue<DataPackage> dataStream = dataStreams.get(dataPackage.getId());
                if(dataPackage.isEnd()) {
                    this.dataStreams.remove(dataPackage.getId());   
                    handNewDataPackage(dataPackage, dataStream);
                }                   
            }

            income = new byte[DataPackage.MAXPACKAGELENGTH];
        }
    } catch (IOException e) {
        e.printStackTrace();
        if(this.client.run() && !ended){
            this.client.endClient();
            this.client.connectionLost(new ClientLostConnectionToServerEvent(this.socket));
        }
        ended = true;
    }
}

Вот как я настраиваю соединение:

socket = new Socket(ip, port);
        socket.setTcpNoDelay(false);
        socket.setReceiveBufferSize(DataPackage.MAXPACKAGELENGTH);
        socket.setSendBufferSize(DataPackage.MAXPACKAGELENGTH);

        this.out = new BufferedOutputStream(socket.getOutputStream(), DataPackage.MAXPACKAGELENGTH);
        this.in = new BufferedInputStream(socket.getInputStream(), DataPackage.MAXPACKAGELENGTH);

Вы можете просмотретьвесь проект (если хотите) здесь: https://github.com/reschiram/Game (новейшая ветвь: G-9)

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

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