Подтвердить что ты не робот

Мой провайдер вынуждает меня буферизовать данные tcp перед отправкой

У меня есть игровой сервер Java TCP, я использую java.net.ServerSocket, и все работает отлично, но недавно мой интернет-провайдер сделал какое-то обновление, где, если вы отправляете два пакета очень быстро для одной и той же TCP-связи, они закройте его силой.

Вот почему многие мои игроки случайно отключены, когда в игре много трафика (когда есть много шансов, что сервер отправит 2 пакета одновременно для одного и того же человека)

Вот пример того, что я имею в виду: Если я сделаю что-то подобное, мой интернет-провайдер закроет связь без каких-либо причин как на стороне клиента, так и на стороне сервера:

tcpOut.print("Hello.");
tcpOut.flush();

tcpOut.print("How are you?");
tcpOut.flush();

Но он будет работать отлично, если я сделаю что-то вроде этого:

tcpOut.print("Hello.");
tcpOut.flush();

Thread.sleep(200);

tcpOut.print("How are you?");
tcpOut.flush();

Или это:

tcpOut.print("Hello.");
tcpOut.print("How are you?");
tcpOut.flush();

Это началось только пару недель назад, когда они (ISP) внесли некоторые изменения в службу и в сеть. Я заметил использование Wireshark, что у вас должно быть не менее ~ 150 мс между двумя пакетами для той же TCP-связи, иначе он будет закрыт.

1) Вы, ребята, знаете, что называется? действительно ли это даже имя? Является ли это законным?

Теперь мне нужно перезаписать свой игровой сервер, зная, что я использую метод: send(PrintWriter out, String packetData);

2) Есть ли простое решение спросить java для буферизации данных, прежде чем отправлять их клиентам? Или ждать 150 мс перед каждой отправкой, не переписывая все это? Я сделал некоторые поисковые запросы, но я не могу найти ничего, что касается этой проблемы. Любые советы или информация, чтобы помочь в этом, были бы очень оценены, btw оптимизация скорости очень важна. Спасибо.

4b9b3361

Ответ 1

Вы можете создать реализацию обертки Writer, чтобы отслеживать последнюю метку времени вызова flush. Быстрая реализация заключается в том, чтобы добавить вызов ожидания, чтобы почтить задержку 150 мс между двумя последовательными сбросами.

public class ControlledFlushWriter extends Writer {
    private long enforcedDelay = 150;
    private long lastFlush = 0;
    private Writer delegated;

    public ControlledFlushWriter(Writer writer, long flushDelay) {
        this.delegated = writer:
        this.enforcedDelay = flushDelay;
    }

    /* simple delegation for other abstract methods... */

    public void flush() {
        long now = System.currentTimeMillis();
        if (now < lastFlush + enforcedDelay) {
            try {
                Thread.sleep(lastFlush + enforcedDelay - now);
            } catch (InterruptedException e) {
                // probably prefer to give up flushing 
                // instead of risking a connection reset !
                return;
            }
        }
        lastFlush = System.currentTimeMillis();
        this.delegated.flush();
    }

}

Теперь должно быть достаточно, чтобы обернуть существующий PrintWriter с помощью этого ControlledFlushWriter для обхода вашего QoS-провайдера без повторной записи всего вашего приложения.

В конце концов, кажется разумным предотвратить соединение с флагом любого из его пакетов как срочное... В таком состоянии трудно реализовать справедливое распределение ссылок QoS.

Ответ 2

Если ваш интернет-провайдер накладывает такое качество политик обслуживания, и у вас нет способа согласовать их с ним, я предлагаю вам обеспечить соблюдение этих правил на вашей стороне с конфигурацией QoS с протоколом TCP/IP.

Флеш отмечает ваш TCP-пакет как срочный (флаг URG), так что он отправляется независимо от состояния окна buffer/TCP. Теперь вы должны сообщить своей операционной системе или любому сетевому оборудованию на линии либо

  • игнорировать (или просто reset) флаг срочности, когда предыдущий пакет был отправлен за последние 150 мс, и при необходимости выполните некоторую буферизацию
  • задерживает доставку последовательных срочных пакетов для соблюдения ограничения 150 мс.

Возможно, для этого существует дорогостоящее программное обеспечение для Windows. Лично я считаю, что ящик Linux как маршрутизатор между вашими рабочими станциями Windows и модемом с соответствующими настройками QoS в iptables и qdisc сделает трюк.