Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > Неблокируемая отправка


Автор: GrayCardinal 2.10.2006, 13:41
Как реализуется ? Знаю что есть poll, который может проверить когда можно отправлять, знаю что send на "неблокируемый" сокет вернет сколько байт отправлено... Т.е. мне надо хранить кучу PTR'ов и организовывать логику отправки "по кусочкам"...... Вопрос - как это сделать по-людски ? Сделать в смысле следующее :
1. Есть дескриптор, в который отправляем файлО. (гигов эдак десять).
2. Есть второй дескриптор, который должен в интерактивном режиме реагировать на команды. 
Чего делать ?

Доп. условия :
Поток отправки не создавать. Ну не нужен мне лишний процесс  smile 




Автор: ZeusAtVingrad 2.10.2006, 14:10
Может select'ом следить за обоими дескрипторами?

Автор: MAKCim 2.10.2006, 15:32
Цитата

Доп. условия :
Поток отправки не создавать. Ну не нужен мне лишний процесс 

а чего так, вроде при COW создание процесса не так расточительно
а вообще может так с select-ом
Код

int socket_id, interactive_id;
...
fd_set read_set, write_set;
int max_id = socket_id > interactive_id ? socket_id + 1: 
    interactive_id + 1;
struct timeval tv = { 0 };
while (1)
{
    FD_ZERO(&read_set);
    FD_ZERO(&write_set);
    FD_SET(socket_id, &write_set);
    FD_SET(interactive_id, &read_set);
    select(max_id, &read_set, &write_set, NULL, &tv); /* не блокируется */
    if (FD_ISSET(interactive_id, &read_set))
    {
         /* читаем, выполняем интерактивные команды */
    }
    if (FD_ISSET(socket_id, &write_set))
    {
        /* отправляем очередную порцию данных через сокет */
    }
}

еще можно таймер поставить, чтобы одна операция другую по времени не вытеснила

Автор: smalcom 2.10.2006, 20:36
без лишнего процесса мона юзать sleep(MAX_DWORD) который совсем не жрет процессор. чем не нравится создать новый тред или вкинуть select в while(true)

Автор: dmiceman 3.10.2006, 01:58
варианты:

1. select()/poll() (это одно и тоже)
2. спать по милисекундам
3. треды
4. ловить SIGIO выставив сокет в O_ASYNC (никогда таким извращением не занимался)
5. форкаться, делать в дите всю работу и умирать

при всем богатстве выбора, альтернативы вариантам 1 и 3 нет. 5 -- по обстоятельствам.

Автор: GrayCardinal 3.10.2006, 08:53
MAKCim
Как определять размер "очередной порции", чтоб небыло блокировки ?

Добавлено @ 08:55 
dmiceman
Меня именно интересует вариант реализации при помощи select/poll. Если я после select что-то оправлю и канал окажется уже, прога у меня заблокируется до окончания передачи  smile 

Автор: smalcom 3.10.2006, 09:32
а если вынести отправку в отдельный тред, то все будет в порядке

Автор: GrayCardinal 3.10.2006, 09:34
smalcom
Предлагаешь создавать тред, который 99.99% своего времени будет простаивать (ожидая завершения отправки) ?  smile 

Автор: smalcom 3.10.2006, 09:49
пусть себе стоит он шо мешает. а во вторых почему стоит?

Автор: GrayCardinal 3.10.2006, 09:55
smalcom
Ну не лежит же  smile 

Автор: smalcom 3.10.2006, 09:58
как тока упадет бум его пороть

Автор: dmiceman 3.10.2006, 17:30
Цитата(GrayCardinal @ 3.10.2006,  08:53)
Добавлено @ 08:55 
dmiceman
Меня именно интересует вариант реализации при помощи select/poll. Если я после select что-то оправлю и канал окажется уже, прога у меня заблокируется до окончания передачи  smile

ты не можешь определить размер рабочей порции. то есть тебе нужно иметь буфер отправки и буфер приема. писать и читать в дескрипторы следует в неблокирующем режиме (O_NONBLOCK). read() и write() для того и возвращают размер принятых/отправленных байт. и на оба дескриптора сажается select() в цикле.

потом, если в командный дескриптор пришла полная команда -- обрабатывай. как ты будешь определять полная ли это команда сидит в буфере -- зависит от задачи. большинство демонов с текстовым интерфейсом (pop3, ftp, smtp) разделяют команды переводами строк.

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

Автор: MAKCim 3.10.2006, 17:40
Цитата

Как определять размер "очередной порции", чтоб небыло блокировки ?

Поставь O_NONBLOCK на сокет
Насколько я знаю для каналов в этом случае возможна частичная запись если размер передаваемых данных больше текущей вместимости буфера. По идее с сокетами тоже должно работать, но не уверен
Еще по-моему в настройках сокета с помощью setsockopt можно указать нижнию границу объема передаваемых данных, и если количество данных меньше чем это граничное значение, write на сокете не блокируется
Цитата

Предлагаешь создавать тред, который 99.99% своего времени будет простаивать (ожидая завершения отправки) ?

Мне кажется все таки использование здесь потоков/процессов логичнее, имхо, конечно

Автор: GrayCardinal 5.10.2006, 07:15
Угу. Всем спасибо... Остановился на варианте с вилкой. Написал Dtransmit которая файло перекидывает и забыл  про траблу smile И не волнует что она в другом процессе выполняется smile 

Автор: Нонейм 10.10.2006, 09:30
Асинхронный ввод-вывод: aio_xxx

Автор: GrayCardinal 11.10.2006, 13:17
Нонейм
Это и есть вариант с новым процессом на каждую передачу.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)