Сокеты Java - убедитесь, что одно клиентское соединение обслуживается раньше других

У меня есть несколько клиентских сокетов TCP, подключающихся к сокету сервера. В этом нет ничего необычного. В эти сокеты периодически поступают данные, которые необходимо обрабатывать сокетам сервера. В течение некоторых периодов поток данных от клиентов к серверу будет почти непрерывным.

Моя проблема в том, что мне нужно убедиться, что данные, поступающие в одно соединение сокета, обслуживаются сервером до того, как данные поступят из других. Только после того, как данных по этому «особому» соединению больше не будет, я должен прочитать данные с других клиентов.

Прямо сейчас у меня есть подход «поток на клиента», который я не думаю, что это лучшее решение для моего случая. Дело в том, что быстрое «специальное» соединение — это своего рода новое требование. Итак, прямо сейчас я ищу способы удовлетворить это требование, не переписывая уже имеющуюся у меня обработку сокетов.

Какие-либо предложения? Большое Вам спасибо.


person ovdsrn    schedule 24.08.2011    source источник
comment
Разве установка приоритетов потоков не сможет дать вам это? Для обычного клиента создайте поток с обычным приоритетом, а для специального клиента создайте поток с более высоким приоритетом.   -  person arunkumar    schedule 24.08.2011
comment
Да, я мог бы это сделать, но при этом есть ли у меня гарантия, что я всегда буду читать быстрое соединение раньше других?   -  person ovdsrn    schedule 24.08.2011
comment
Ты прав. Взгляните на этот вопрос SO - stackoverflow.com/questions /128039/ . Ссылка в ответе указывает на ошибку в реализации планирования потоков JVM. Существует также ссылка на эффективное руководство по программированию на Java, в котором может быть решение для планирования потоков.   -  person arunkumar    schedule 24.08.2011


Ответы (2)


Вам нужно будет реализовать какой-то алгоритм планирования/качества обслуживания. В самой простой форме это действительно может быть просто «пока есть данные в специальном сокете, не беспокойтесь о других сокетах».

Эта простая модель может быть достигнута, например, с двумя списками:

  1. Один список специальных розеток
  2. Один список обычных сокетов.

Один рабочий читает сокеты и записывает в очередь. Прочитав небольшое количество байтов, он проверяет, есть ли данные в специальных сокетах. Если это так, сначала прочитайте специальные сокеты, а затем продолжите работу с другими сокетами. Хитрость заключается в том, чтобы считывать данные достаточно маленькими порциями, чтобы иметь возможность переключаться достаточно быстро, но не слишком маленькими, чтобы потерять всю эффективность. Так же работает планирование для ЦП.

Имейте в виду, что при чтении только специальных сокетов, пока в специальных сокетах есть данные, другие сокеты могут вообще не читаться. Если вы этого не хотите, рассмотрите алгоритмы планирования, такие как Взвешенная справедливая организация очереди или Взвешенный циклический перебор.

person Konerak    schedule 24.08.2011

Как отметил @Konerak, вам придется реализовать некоторую форму QoS.

Вы можете попытаться определить тип данных для ваших сообщений, с которыми вы их инкапсулируете, а затем добавить тег, чтобы отметить, что определенное сообщение имеет определенный вид (например, ваш специальный сокет). Затем, когда сервер получает сообщение, вы можете вставить сообщение в очередь, где вы начнете выполнять. Сначала выполните все сообщения, помеченные как «специальные» (или то, что вы хотите использовать), а затем перейдите ко всем сообщениям без тега. Очередь (FIFO) гарантирует, что все сообщения обрабатываются по мере их поступления. Обязательно ознакомьтесь с методом Peek очереди ( http://download.oracle.com/javase/1,5.0/docs/api/java/util/Queue.html).

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

Вы также можете сохранить метод Thread per Client. Это вполне нормально в небольшой среде, где подключено всего несколько клиентов, но по мере того, как вы начнете масштабироваться до больших чисел, вам, возможно, придется подумать об использовании NIO. Но, как я уже сказал, оба подхода являются допустимыми, каждый со своими плюсами и минусами.

Просто идея и пара моментов для размышления.

person Johann du Toit    schedule 24.08.2011
comment
Насколько мне известно (а я знаю не слишком много), с помощью NIO можно указывать предпочтительные каналы. Но переход на NIO, вероятно, потребует некоторых изменений в коде. Я прав? - person ovdsrn; 24.08.2011
comment
Да, поэтому я поставил внизу и попытался придумать что-то, что позволит вам сделать QoS с вашим текущим кодом и минимальными изменениями. - person Johann du Toit; 24.08.2011
comment
@ovdsrn «Насколько я знаю (и я не слишком много знаю), с помощью NIO вы можете указать предпочтительные каналы»: нет, вы не можете. Эта особенность воображаемая. - person user207421; 24.08.2011
comment
Итак, я не сошел с ума, искал предпочтительные каналы в Google и не смог найти... - person Johann du Toit; 24.08.2011
comment
В начале главы о NIO в этой книги, аргументируя необходимости NIO, он говорит что-то вроде: - person ovdsrn; 24.08.2011
comment
Если бы это было все, что нужно, NIO мог бы и не понадобиться. К сожалению, есть и другие, более тонкие проблемы, связанные с использованием потоков для масштабируемости. Во-первых, у программиста очень мало контроля над тем, какие потоки и когда будут получать обслуживание. Вы можете установить приоритет экземпляра Thread (потоки с более высоким приоритетом получают преимущество перед потоками с более низким приоритетом), но, в конечном счете, приоритет является просто «советом» — какой поток выбирается для запуска следующим, полностью зависит от реализации. - person ovdsrn; 24.08.2011
comment
Таким образом, если программист хочет гарантировать, что определенные соединения будут обслуживаться раньше других, или установить определенный порядок обслуживания, потоки могут затруднить это. Отсюда я делаю вывод, что с помощью NIO можно указать, какое соединение нужно обслуживать в первую очередь. Я прочитаю главу более внимательно, чтобы увидеть, как это можно сделать. - person ovdsrn; 24.08.2011
comment
Спасибо за фрагменты, пожалуйста, держите меня в курсе, мне бы очень хотелось узнать об этой загадочной функции, если она существует. Если вы найдете какие-либо ссылки; они бы тоже помогли. - person Johann du Toit; 24.08.2011