Я пишу клиент-серверное приложение, в котором несколько клиентов подключаются к серверам и непрерывно отправляют сериализованные объекты на серверы с высокой скоростью через TCP-соединение.
Я использую ObjectOutputStream.writeObject на клиенте и ObjectInputStream.readObject на сервере.
Серверное приложение принимает подключение клиентов на один порт с помощью serverSocket.accept() и передает Socket новому потоку для чтения объектов.
Когда один клиент подключается и отправляет около 25 тыс. объектов/с - все работает нормально. Как только я запускаю второго клиента, через короткий промежуток времени один или оба клиента зависают на ObjectOutputStream.writeObject для одного из серверов, а соответствующий сервер зависает на ObjectInputStream.readObject. Никаких исключений с обеих сторон.
Если скорость очень низкая, скажем 10-20/с суммарно - зависать не будет, а вот при 100-1000/с будет.
Используя netstat -an
на клиентской машине, я вижу, что send-Q
соответствующей ссылки составляет около 30 КБ. На стороне сервера receive-Q
также составляет ~ 30 КБ.
При запуске клиента/сервера на локальной винде наблюдаю нечто похожее - клиент зависает, но сервер продолжает обрабатывать входящие объекты и как только догоняет, клиент разблокируется и продолжает отправлять объекты.
Локально в Windows сервер работает медленнее, чем клиент, но в Linux количество экземпляров сервера, работающих на разных машинах, более чем достаточно для скорости, которую производят клиенты.
Любая подсказка, что происходит?
фрагмент кода клиента:
Socket socket = new Socket(address, port);
ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
while(true)
{
IMessage msg = createMsg();
outputStream.writeObject(msg);
outputStream.flush();
outputStream.reset();
}
код сервера, принимающий соединения:
while(active)
{
Socket socket = serverSocket.accept();
SocketThread socketThread = new SocketThread(socket);
socketThread.setDaemon(true);
socketThread.start();
}
объекты чтения кода сервера:
public class SocketThread extends Thread
{
Socket socket;
public SocketThread(Socket socket)
{
this.socket = socket;
}
@Override
public void run() {
try {
ObjectInputStream inStream = new ObjectInputStream(socket.getInputStream());
while(true)
{
IMessage msg = (IMessage)inStream.readObject();
if(msg == null){
continue;
}
List<IMessageHandler> handlers = handlersMap.get(msg.getClass());
for(IMessageHandler handler : handlers){
handler.onMessage(msg);
}
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
readObject()
не вернет значение null, если вы не отправите значение null. Если вы не планируете этого делать, нулевой тест не имеет смысла. - person user207421   schedule 17.06.2016