ПрограммированиеФорумСеть

По несколько сокетов на поток (2 стр)

Страницы: 1 2 3 4 5 Следующая »
#15
14:40, 6 апр 2011

Серый крокодильчик
> зачем несколько селектов в разных потоках?
Я и спрашиваю как по другому разбить на потоки по 1000к конектов? Я сделал так, что у меня в каждом потоке селект только для сокетов из текущего потока. Например при 2к конектов, каждый поток будет содержать 1000к конектов, и 1 селек будет привязан к 1к сокетов.
Вот если юзать только один селект, то как осуществить разбитие на патоки я не представляю...

Я не говорю что так надо) я спрашиваю как надо правильно?)

Серый крокодильчик
> тем более с selectNow
по одной простой причине... если я добавляю новый сокет в поток, а селект в данный момент висит, то новый сокет не добавится пока како либо из сокетов не сработает на чтение или запись. Я думал не селектНов использовать а например селект(1000) чтоб каждую секунду например выполнялся цикл.

Серый крокодильчик
> чтение из сокета в финали - это жесть
Это вообще просто так) обработку ошибок я кликал в эклипсе по крестикам и она вставляла мне блоки try, я это пока не продумывал :)

Серый крокодильчик
> Логгирование в вашем случае удобнее через Logger, а не этот самопал.
В данном случае самопал на время теста, потом будет класс логирования, с записью в файл.

#16
14:51, 6 апр 2011

slava_mib
> Easy, конечно "как в универе учили". Так просто, понятно и ничего лишнего.
> Правка: только старайся псевдо-код писать на более высоком уровне. Не надо там
> "прочитать N байт из сокета, если не было ошибки, взывать функцию парсинга,
> передав ей байты". Просто пиши "читаем данные, передаём в парсер".

1. Создаём класс, который отвечает за распределение по потокам клиентов.
2. Открываем сокет, ждём клиента
3. Добавляем клиента в класс из 1.

4. проверяем если есть в созданных потоках пустое место то добавляем сокет иначе создаём поток и добавляем сокет.

5. добавили сокет из 4 в поток, у потока свой селект, 1 на поток.
6. в цикле ожидаем select() и проверяем, если read то выполняем чтение из сокета.

вот в 6ом беда. Цикл останавливается на select и функция add() которая добавляет в множество нового клиента не выполняется. Как только один из клиентов уже подключеных в текущем потоке срабатывает, то после этого выполняется add и уже новый клиент добавляется в поток.
Может использовать что то типа select(1000) чтобы раз в секунду поток оживал?)

#17
14:53, 6 апр 2011

Easy
> Я и спрашиваю как по другому разбить на потоки по 1000к конектов?
так у меня вопрос, зачем разбивать по 1000 коннектов на поток?


Easy
> , а селект в данный момент висит,
Selector.wakeup()

#18
14:58, 6 апр 2011

>Цикл останавливается на select
Вообще-то селект тоже бывает не блокируемый.

#19
15:01, 6 апр 2011

Серый крокодильчик
> так у меня вопрос, зачем разбивать по 1000 коннектов на поток?
Ну я как бы в самом первом посте спросил, будет ли прирост производительности? Как я понял всё таки будет.

Серый крокодильчик
> Selector.wakeup()
Спасибо! Не знал про эту функцию. Но проблема в том, откуда запускать её? я выполняю t.add() и основной поток виснет, пока второй висит :)

#20
15:03, 6 апр 2011

Easy
> Ну я как бы в самом первом посте спросил, будет ли прирост производительности?
> Как я понял всё таки будет.
нет
Easy
> Спасибо! Не знал про эту функцию. Но проблема в том, откуда запускать её? я
> выполняю t.add() и основной поток виснет, пока второй висит :)
положить сокет в буфер. сделать вейкап
в основном потоке проверить буфер и положить сокет в  селектор

#21
15:09, 6 апр 2011

slava_mib
> ообще-то селект тоже бывает не блокируемый.
Ну так тогда цикл постоянно крутится, хоть и не чего не делает но крутится, точнее он проверяет есть ли кей :) А это дополнительная нагрузка... или нет?

#22
15:11, 6 апр 2011

Серый крокодильчик
> положить сокет в буфер. сделать вейкап
> в основном потоке проверить буфер и положить сокет в  селектор
сокет в переменной c
делаю
t.sel.wakeup();
t.add(c);
не успевает видимо) так как цикл 1 раз проскакивает, а add не срабатывает :(

#23
15:16, 6 апр 2011

>Ну так тогда цикл постоянно крутится, хоть и не чего не делает но крутится, точнее он проверяет есть ли кей :) А это дополнительная нагрузка... или нет?
Угу. Нагрузка. Ты решил от неё избавиться?... Ведь пока в сокетах ничего нет и проц ничего не делает - ОЧЕНЬ важно экономить процессорное время, угу )))

#24
15:20, 6 апр 2011

slava_mib
> Угу. Нагрузка. Ты решил от неё избавиться?... Ведь пока в сокетах ничего нет и
> проц ничего не делает - ОЧЕНЬ важно экономить процессорное время, угу )))
ну как бы не совсем проц не чего не делает.
Выполняется каждый раз вот это

Iterator<SelectionKey> it = sel.selectedKeys().iterator();
while(it.hasNext()) {

цикл вайл не начнётся, так как селектКей пуст, но всё таки что то проверяется...
Или это не нагрузит?

#25
15:25, 6 апр 2011

slava_mib
> Ведь пока в сокетах ничего нет
верно
slava_mib
> проц ничего не делает
неверно
он в это время может быть занят другими задачами, в том числе обработкой прошлых пакетов.
крутить поток в пустую плохая практика, если поток ничего не делает - он должен спать. Иначе он будет давать
туже нагрузку что и работающий.
Easy
> не успевает видимо) так как цикл 1 раз проскакивает, а add не срабатывает :(
t.putBuffer(c);
t.sel.wakeup();
а уже внутри run
if(!buffer.isEmpty()){
  add(buffer.poll());
}

#26
15:28, 6 апр 2011

> крутить поток в пустую плохая практика, если поток ничего не делает - он должен
> спать. Иначе он будет давать
> туже нагрузку что и работающий.
Серый крокодильчик, для этого есть sleep )

#27
15:40, 6 апр 2011

Вот так изменил, работает с блокирующим сокетом) Спасибо!

public void add(SocketChannel c) throws IOException {
    boolean add = false;
    LoginServer.pDebug("added new sock");
    for (ClientThread t: threads) {
      if (t.Clients().size() < max_clients) {
        t.buf.add(c);
        t.sel.wakeup();
        add = true;
        break;
      }
    }
    if (!add) {
      ClientThread t = new ClientThread();
      t.buf.add(c);
      t.sel.wakeup();
      threads.add(t);
      t.start();
    }
  }
public Set<SocketChannel> buf = new HashSet<SocketChannel>();
public void run() {
    while(true) {
      try {
        sel.select();
      } catch (IOException e) {
        LoginServer.pDebug("ClientThread -> run -> select");
        e.printStackTrace();
      }
      if (!buf.isEmpty()) {
        for (SocketChannel newSc: buf)
          try {
            add(newSc);
          } catch (ClosedChannelException e) {
            e.printStackTrace();
          }
      }
      Iterator<SelectionKey> it = sel.selectedKeys().iterator();
      while(it.hasNext()) {
        SelectionKey key = it.next();
        it.remove();
        if (key.isValid()) {
          LoginServer.pDebug("key valid");
          if (key.isReadable()) {
            try {
              read(key);
            } catch (IOException e) {
              LoginServer.pDebug("ClientThread -> run -> read : " + key.channel());
              cs.remove(key.channel());
              if (key.channel() != null)
                try {
                  key.channel().close();
                } catch (IOException e1) {
                  LoginServer.pDebug("ClientThread -> run -> read/close");
                  e1.printStackTrace();
                }
              e.printStackTrace();
            }
          }
        }
      }
    }
  }

Ну так вообще такая реализация имеет место жить?) Или всё таки лучше в один поток всех клиентов запихивать?

> для этого есть sleep )
ну я как бы и намекал на это select(1000) то же самое что selectNow(); sleep(1000);

#28
15:43, 6 апр 2011

slava_mib
> Серый крокодильчик, для этого есть sleep )
слип - слипом, селект - селектом. :)

#29
18:42, 6 апр 2011

Что ж это творится такое. Набежали велосипедисты. Сажи велосипедистам ;)

В порядке обучения пусть человек поюзает какуюто сложную (вроде ASIO для С++ только для явы) или простую либу (вроде Win32 IOCP или там libev для линуха) для асинхронки.
Поюзает, разберётся как все работает, пусть потом лезет в сокеты, флаги, селекты и прочий хлам.

Страницы: 1 2 3 4 5 Следующая »
ПрограммированиеФорумСеть

Тема в архиве.