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


Автор: En_t_end 5.3.2006, 07:59
Под winsock я юзал механизм не блокирующих сокетов, примерно так:
timeval ReceiveTimeout;
ReceiveTimeout.tv_sec = time_out;
ReceiveTimeout.tv_usec = 0;
fd_set fds;
while(recived < len)
{
FD_ZERO(&fds);
FD_SET(sock,&fds);
select(0, &fds, NULL, NULL, &ReceiveTimeout);
if(FD_ISSET(sock, &fds))
{
//принимаем
}
else
{
//тайм аут
}
}
В *nix я получил эффект простого засыпания программы(или сокета), что мне совсем не нравится.

Автор: bilbobagginz 6.3.2006, 00:51
тебе надо почитать man select.
таймаут нужно ставить подходящий или 0.
кстати, о каком UNIX идет речь ?


пока.

Автор: En_t_end 6.3.2006, 18:39
bilbobagginz
linux redhat.
читал я man(также читал о переходе на кроссплатформенное программирование сокетов), понял, что select особо чувствителен к storage, в котором лежат handle(или их прототипы)... таймаут ставлю в пределах 40 секунд. Для теста посылаю данные, но select на другом конце игнорит readfs, smile честно меня это очень смешит, а потом, когда на другом конце клиент говорит что таймаут, всё сервер не отвечает, пора дисконнектиться, тут просыпается сервер и говорит, что соединение разорванно, причем, если попытаться прочитать то что находиться в стеке recv'ом, то там будет как раз то, что пришло. Так что точно отбрасывается то, что данные не доходят.

Автор: bilbobagginz 7.3.2006, 01:32
мне кажется что плохо настроены сокеты .. ( либо сервера либо клиента либо обоих. )
сокет не будет каждый символ создавать событие, поэтому, вопрос каждые сколько символов твой сокет создает событие ? ты это настраивал ?
не обижайся, но можно посмотреть коммуникационный код? ( включая настройки сокетов )

Автор: En_t_end 7.3.2006, 09:18
Короче я пришел к выводу, что я чего-то не до понял, походу в linux автоматически не генерятся событие onread у сокетов. Пожалуйста скажите каким образом можно настроить сокет(под linux) чтобы он менял состояние на onread, которое можно отлавливать select'ом. Извиняюсь за тупость.

Автор: En_t_end 14.3.2006, 10:07
Товарищи, я не могу добиться желаемого эффекта уже неделю, откликнитесь!

Автор: AndrK 12.7.2006, 18:01
Первый параметр в select - это максимальный дескриптор+1, в твоем случае sock+1,
а у тебя он 0...
здесь поможет man select...
ЗЫ... кстати, в винде он игнорируется, может это тебя ввело в заблуждение...
 

Автор: MastEdm 12.7.2006, 19:33
Разберёмся на примерах...
Код

#include <unistd.h>
#include <fcntl.h>
...
sockfd = socket(AF_INET, SOCK_STREAM, 0);
fcntl(sockfd, F_SETFL, O_NONBLOCK);
...

Такая операция превращает сокет в неблокирующий. Вызов любой функции с таким сокетом будет возвращать управление немедленно.

Теперь об использовании самого select'а. 
Код

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int select(int n, fd_set *readfds, fd_set *writefds,
                fd_set *exceptfds, struct timeval *timeout);

FD_CLR(int fd, fd_set *set);
FD_ISSET(int fd, fd_set *set);
FD_SET(int fd, fd_set *set);
FD_ZERO(int fd);

Функция select работает с тремя множествами дескрипторов, каждое из которых имеет тип fd_set. В множество readfds записываются дескрипторы сокетов, из которых нам требуется читать данные (слушающие сокеты добавляются в это же множество). Множество writefds должно содержать дескрипторы сокетов, в которые мы собираемся писать, а exceptfds - дескрипторы сокетов, которые нужно контролировать на возникновение ошибки. Если какое-то множество нас не интересуют, мы можем передать вместо указателя на него NULL. Что касается других параметров, в n нужно записать максимальное значение дескриптора по всем множествам плюс единица, а в timeout - величину таймаута. Структура timeval имеет следующий формат:
Код

struct timeval {
    int tv_sec;     // секунды
    int tv_usec;    // микросекунды
};

Если хотя бы один сокет готов к выполнению заданной операции, select возвращает ненулевое значение, а все дескрипторы, которые привели к "срабатыванию" функции, записываются в соответствующие множества. Это позволяет нам проанализировать содержащиеся в множествах дескрипторы и выполнить над ними необходимые действия. Если сработал таймаут, select возвращает ноль, а в случае ошибки -1. Расширенный код записывается в errno.

Вот в двух словах о работе select... 

Автор: Pete 16.7.2006, 23:09
Да, не забудь, что select() изменяет fd_set:
Цитата
http://www.opennet.ru/man.shtml?topic=select&category=3&russian=5

  

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