2015-01-28 1 views
2

В настоящее время у меня есть сервер, который слушает подключения (это базовый сервер рекордов для мобильной игры, который у меня есть), через каждые 1000 мс и прослушивает любые входящие данные.Make notStreaming InputStream

public void readData(Connection c) throws IOException { 
    PacketBuffer readBuffer = new PacketBuffer(Server.PACKET_CAPACITY); 
    int packetSize = c.getIn().read(); 
    c.getIn().mark(packetSize); 
    byte[] buffer = new byte[packetSize]; 
    c.getIn().read(buffer, 0, buffer.length); 
    readBuffer.setBuffer(buffer); 
    packetHandler.addProcess(c, readBuffer); 
} 

Я использую свой собственный PacketBuffer и мне нужно найти способ, так что c.getIn(). Чтения() (Это мое соединение InputStream) не блокирует. В настоящее время сокет установлен в тайм-аут 500 мс, и мой сервер будет работать нормально. Моя проблема заключается в том, что если кто-то пытается создать свою собственную программу для подключения, чтобы попытаться взломать собственные рекорды или сервер ddos, он будет запутан с помощью пута бесполезных соединений, которые блокируют поток на 500 мс, когда соединение не записывается.

+1

Это звучит как работа для Netty вместо рукописного кода отправки. – chrylis

ответ

3

Вы можете попробовать что-то вроде этого. Каждый раз, когда вызывается readData, он проверяет, доступны ли байты для чтения. Я использовал , в то время как цикл здесь, потому что вы хотите, чтобы он обрабатывал все данные, которые он может, прежде чем поток снова спит. Это гарантирует, что сообщения не будут скопированы, если бы их читать только один раз каждые миллисекунды.

public void readData(Connection c) throws IOException { 
    while (c.getIn().available() > 0) { 
     int packetSize = c.getIn().read(); 
     c.getIn().mark(packetSize); 
     byte[] buffer = new byte[packetSize]; 
     c.getIn().read(buffer, 0, buffer.length); 
     PacketBuffer readBuffer = new PacketBuffer(Server.PACKET_CAPACITY); 
     readBuffer.setBuffer(buffer); 
     packetHandler.addProcess(c, readBuffer); 
    } 

Я не знаю, почему вы используете метод меток. Мне кажется проблематичным.

Вам также действительно нужно использовать метод стиля readFully() (см. DataInputStream), который не вернется, пока он определенно не прочитает полный массив байтов. Регулярные чтения всегда могут «возвращаться короткими», даже когда отправитель отправил полный блок данных (из-за размера сетевого пакета и т. Д.).

0

Вы не можете. InputStreams блокируются. Период. Трудно понять, как неблокирующий режим действительно решит проблему, о которой вы говорите. Я предлагаю, чтобы редизайн был в порядке.

2

Существует два классических способа реализации серверов в Java.

Первый и самый старый способ - использовать пару потоков чтения/записи для каждого подключенного клиента. Это нормально для небольших серверов без большого количества подключенных клиентов, так как каждому клиенту требуется два потока для управления им. Он не очень хорошо масштабируется для многих одновременных клиентов.

Второй и более новый способ заключается в использовании java.nio.ServerSocketChannel, java.nio.SocketChannel и java.nio.Selector. Эти три класса позволяют управлять всеми операциями ввода-вывода для каждого клиента, подключенного в одном потоке. - пример того, как реализовать очень простой сервер, используя пакет java.nio.

Лучшим способом реализации сервера будет использование сторонней структуры. Большая библиотека, которую я использовал в прошлом, - Netty. Он обрабатывает все мелкие детали сокетов и обеспечивает довольно чистый и простой api, который хорошо масштабируется.

Смежные вопросы