Форум программистов, компьютерный форум, киберфорум
C++: Сети
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.93/41: Рейтинг темы: голосов - 41, средняя оценка - 4.93
Эксперт С++
 Аватар для Avazart
8483 / 6150 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
1

Реализовать таймаут

16.11.2012, 19:47. Показов 8005. Ответов 29
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Допустим есть пишем класс обвертку над winsocks.

Как реализовать таймаут соединения.

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

C++ Скопировано
1
2
3
4
5
6
7
8
9
10
bool some_class::some_method(std::string msg, std::string& result)
{
  // код отправки msg
    if( ! Ok )  return false;
 
  // код приема в result , и если не удалось принять Ok = 0;
  if( ! Ok )  return false;
 
  return true; 
}
Вообще и без многопоточности подобно Indy - компонентам
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
16.11.2012, 19:47
Ответы с готовыми решениями:

Таймаут?
Доброго времени суток! Подскажите пожалуйста что использовать чтобы реализовать описанное ниже? Каждую, например, секунду...

Синхронные сокеты и таймаут
Решил соорудить небольшой наколенный многопоточный клиент dht . Есть некоторые вопросы по сокетам и гугол как-то больше молчит . ...

Как организовать таймаут?
Как сделать так чтобы, допустим клиент отправил серверу данные по TCP. Сервер принял и отправляет ответ клиенту. И пока клиент не прочтет...

29
204 / 205 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
17.11.2012, 20:48 2
Ожидай данные select'ом либо IOCP. Закончится время - кидай исключение.
0
Эксперт С++
 Аватар для Avazart
8483 / 6150 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
17.11.2012, 20:50  [ТС] 3
А пример можно или псевдокод?

select вроде только проверяет наличия соединения или я ошибаюсь?
0
204 / 205 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
17.11.2012, 20:59 4
select проверяет готовность сокета. К соединению или чтению не важно.
C++ Скопировано
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
       bool wait_for_read( DWORD timeout = INFINITE ) const {
 
            fd_set recv_set = {0};
 
            timeval tv = {0};
            timeval *tvp;
 
            if (timeout == INFINITE) {
                tvp = NULL;
            } else {
                tv.tv_sec = timeout / 1000;
                tv.tv_usec = (timeout % 1000) * 1000;
                tvp = &tv;
            }
            FD_SET(sock, &recv_set);
            int res = 0;
            res = ::select(sock + 1, // useless in windows
                            &recv_set, NULL, NULL, tvp);
            // res == -1 -- throw ... 
            return (res != 0);
        }
1
Эксперт С++
 Аватар для Avazart
8483 / 6150 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
17.11.2012, 21:28  [ТС] 5
Ну так если сначала проверим и сразу читаем, то нормально будет ?
Теоретически ведь соединение может упасть в промежутке между этими действиями- это меня заботит.

Или я неправильно понимаю- select говорит о уже принятой информации и готовой к чтению ?

IOCP как понимаю для не блокируемого режима

Добавлено через 20 минут
С помощью функции select и этого набора макросов, мы можем проверять конечное множество сокетов на готовность к считыванию/отсылке данных, выполнения connect, на предмет входящих соединений, наличия OOB сообщений и т.п. На данном этапе нас интересует проверка сокета на возможность считывания данных, поэтому пока ограничимся самым простым вызовом select. Для этого нам необходимо поместить наш сокет в множество на которое будет указывать readfds (в примере это read_s), задать timeout и выполнить select.
http://club.shelek.ru/viewart.php?id=37

Здесь имеется ввиду готовность нашего клиент-сокета или сокет-сервера на той стороне соединения ?
Вот что мне непонятно...
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
17.11.2012, 21:49 6
Для блокируемых сокетов иногда бывает проще поставить SO_(RCV|SND)TIMEO
0
Эксперт С++
 Аватар для Avazart
8483 / 6150 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
17.11.2012, 21:51  [ТС] 7
g_u_e_s_t, А по подобнее ?
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
17.11.2012, 21:56 8
Посредством setsockopt() выставляем максимальное время ожидания для операций чтения/записи на сокете. Т.е. например recv() будет ждать данных не "вечно" а N секунд.
0
Эксперт С++
 Аватар для Avazart
8483 / 6150 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
17.11.2012, 22:31  [ТС] 9
Т.е имеется ввиду SO_RCVTIMEO и SO_SNDTIMEO
SO_RCVTIMEO DWORD Sets the timeout, in milliseconds, for blocking receive calls.
SO_SNDTIMEO DWORD The timeout, in milliseconds, for blocking send calls.
http://msdn.microsoft.com/en-u... 85%29.aspx

Как я понимаю в случае таймаута будет возвращено SOCKET_ERROR ?
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
17.11.2012, 22:47 10
Там же все написано...
0
Эксперт С++
 Аватар для Avazart
8483 / 6150 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
18.11.2012, 03:10  [ТС] 11
Ну читаю
SO_RCVTIMEO and SO_SNDTIMEO

When using the recv function, if no data arrives during the period specified in SO_RCVTIMEO, the recv function completes. In Windows versions prior to Windows 2000, any data received subsequently fails with WSAETIMEDOUT. In Windows 2000 and later, if no data arrives within the period specified in SO_RCVTIMEO, the recv function returns WSAETIMEDOUT, and if data is received, recv returns SUCCESS.
Только что-то я не пойму это вроде касается level = NSPROTO_IPX, в IPPROTO_TCP вроде ничего не сказано про SO_RCVTIMEO.
Или это лишь уровень на котором задается поведение?

Добавлено через 7 минут
Не туда глянул ....

Добавлено через 13 минут
Как я понимаю приблизительно так должно выглядеть

C++ Скопировано
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
DWORD interval = 1000; // мс
int size = sizeof (DWORD);
//....
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//...
iResult = setsockopt(ListenSocket, SOL_SOCKET, SO_RCVTIMEO,  (char *)&interval,size);
 
if (iResult == SOCKET_ERROR)   
   {
       wprintf(L"setsockopt for SO_KEEPALIVE failed with error: %u\n", WSAGetLastError());
   } 
else
      wprintf(L"SO_RCVTIMEO: ON\n");
 
 
iResult = setsockopt(ListenSocket, SOL_SOCKET, SO_SNDTIMEO,  (char *)&interval, size);
 
if (iResult == SOCKET_ERROR)   
   {
       wprintf(L"setsockopt for SO_SNDTIMEO failed with error: %u\n", WSAGetLastError());
   } 
else
      wprintf(L"SO_SNDTIMEO: ON\n");
Добавлено через 2 часа 23 минуты
В общем теперь пытаюсь реализовать
C++ Скопировано
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//---------------------------------------------------------------------------
bool client_t::connect()
{
    _socket= ::socket(AF_INET,SOCK_STREAM,0);
    if(_socket==INVALID_SOCKET) return false;
 
    if( ::connect(_socket, (sockaddr*)&_addr, sizeof(_addr) ) ) return false;
    else
        {
            #ifdef MyDebug
                std::cerr<<"[Debug] "<<"Соединение установлено."<<std::endl;
            #endif
        }
     /*
    if(setsockopt( _socket, SOL_SOCKET,
                                 SO_RCVTIMEO,
                                 (char *)&_timeout,
                                 sizeof(_timeout) ) == SOCKET_ERROR) return false;
 
    if(setsockopt( _socket, SOL_SOCKET,
                                 SO_SNDTIMEO,
                                 (char *)&_timeout,
                                 sizeof(_timeout) ) == SOCKET_ERROR) return false;
     */
return true;
}
//---------------------------------------------------------------------------
bool client_t::send(std::string cmd)
{
    int length = ::send(_socket, cmd.c_str(), cmd.length(), NULL);
    return length != SOCKET_ERROR;
}
//---------------------------------------------------------------------------
bool client_t::receive(std::string& response)
{
response.clear();
int length= 0;
 
do
    {
        //memset(_buff,'\0',MAX_LENGTH);
        length= ::recv( _socket, _buff, MAX_LENGTH, NULL);
        if(length == SOCKET_ERROR)
            {
             #ifdef MyDebug
                    std::cerr<<"[Debug] "<<"Ошибка чтения."<<std::endl;
             #endif
             return false;
            }
        #ifdef MyDebug
                    std::cerr<<"[Debug] "<<"Принято "<<length<<" Байт"<<std::endl;
        #endif
        response+= std::string(_buff, length) ;
    }
while( length!=0 );
 
return true;
}
//---------------------------------------------------------------------------
C++ Скопировано
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
system("chcp 1251");
system("color 0a");
 
using namespace std;
 
my::client_t client1;
 
client1.set_port(110);
if(! client1.set_addr("pop.yandex.ru") ) client1.get_error();
 
if(! client1.connect() ) client1.get_error();
 
std::string response;
if( ! client1.receive(response) ) client1.get_error();
cout<< response;
 
 
system("pause");
return 0;
}
//---------------------------------------------------------------------------
Получаю
Bash Скопировано
1
2
3
4
5
6
7
8
Текущая кодовая страница: 1251
[Debug] WSA успешно запущена
[Debug] Создан клиент, количество клиентов 1
[Debug] Соединение установлено.
[Debug] Принято 38 Байт   // тут задержка
[Debug] Принято 0 Байт
+OK POP Ya! v1.0.0na@10 6jUYG7JN6qM1
Для продолжения нажмите любую клавишу . . .
Если раскомментировать код с setsockopt получаю ошибку
Bash Скопировано
1
2
3
4
5
6
7
8
9
10
Текущая кодовая страница: 1251
[Debug] WSA успешно запущена
[Debug] Создан клиент, количество клиентов 1
[Debug] Соединение установлено.
[Debug] Принято 37 Байт // Задержка на таймаут
[Debug] Ошибка чтения.
Error #10060 Попытка установить соединение был  // ... бла-бла  - вообщем таймаут
 
+OK POP Ya! v1.0.0na@4 isU07sn5IOs1
Для продолжения нажмите любую клавишу . . .
До этого код работал на колбеке где получение было порциями. А как тут понять что прием закончен ?

Если таймауты не устанавливать, когда прием закончен recv возвращает 0.
А если установлены - ошибку.
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
18.11.2012, 10:21 12
Цитата Сообщение от Avazart Посмотреть сообщение
Как я понимаю приблизительно так должно выглядеть
Честно говоря я не уверен, что в Виндах есть какой-то смысл в этих опциях для listen сокета.
Цитата Сообщение от Avazart Посмотреть сообщение
До этого код работал на колбеке где получение было порциями. А как тут понять что прием закончен ?
Точно так же, ничего не поменялось. Можете сказать серверу quit и убедиться, что после "+ok" recv вернет вам 0.
Цитата Сообщение от Avazart Посмотреть сообщение
Если таймауты не устанавливать, когда прием закончен recv возвращает 0.
А если установлены - ошибку.
Просто таймаут случается раньше чем сервер закрывает сокет.

Если Ваша цель pop3 клиент, то лучше начать не с сокетов и тем более таймаутов, а с реализации FSM.
0
Эксперт С++
 Аватар для Avazart
8483 / 6150 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
18.11.2012, 15:48  [ТС] 13
Цитата Сообщение от g_u_e_s_t Посмотреть сообщение
Просто таймаут случается раньше чем сервер закрывает сокет.
Оуу какой закрывать ? Я ему не говорил закрывать соединение...

Или я что-то не понимаю ? recv возвращает 0 только при закрытие соединения ?

Добавлено через 6 минут
Цитата Сообщение от g_u_e_s_t Посмотреть сообщение
Если Ваша цель pop3 клиент, то лучше начать не с сокетов и тем более таймаутов, а с реализации FSM.
Не уверен в том что вы понимаете под FSM, то логичнее начинать снизу вверх а не на оборот.

А задача понять как приблизительно может работать Indy.

Добавлено через 40 секунд
recv возвращает 0 только при закрытие соединения ?
А как тут понять что прием закончен ?
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
18.11.2012, 16:45 14
Цитата Сообщение от Avazart Посмотреть сообщение
Я ему не говорил закрывать соединение...
Ну вот захотел и закрыл, Ваше "я не говорил" удаленной стороне вообщем случае по барабану... что хочет то и делает
Цитата Сообщение от Avazart Посмотреть сообщение
ли я что-то не понимаю ?
Похоже да.
Цитата Сообщение от Avazart Посмотреть сообщение
recv возвращает 0 только при закрытие соединения ?
Для SOCK_STREAM есть еще вариант recv(,,0,) при котором некоторые системы (например оригинальный BSD стэк) возвращают 0, но это не Ваш случай.
Цитата Сообщение от Avazart Посмотреть сообщение
Не уверен в том что вы понимаете под FSM,
Машина состояний протокола.
Цитата Сообщение от Avazart Посмотреть сообщение
о логичнее начинать снизу вверх а не на оборот.
Угу, заметно.
Цитата Сообщение от Avazart Посмотреть сообщение
А как тут понять что прием закончен ?
Где тут? Я совершенно без понятия, кто такой/ая Ваша Indy...
Если Вы о своем коде с зачатками pop3, то смотреть, что именно ответил сервер после каждого успешного recv().
0
Эксперт С++
 Аватар для Avazart
8483 / 6150 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
18.11.2012, 17:08  [ТС] 15
Цитата Сообщение от g_u_e_s_t Посмотреть сообщение
Если Вы о своем коде с зачатками pop3, то смотреть, что именно ответил сервер после каждого успешного recv().
POP3 лишь пример обмена командами.

Ну так, как я узнаю что ответил полностью, а главное что он закончил отвечать?

Добавлено через 3 минуты
Сервер то может отвечать порциями...
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
18.11.2012, 17:25 16
Цитата Сообщение от Avazart Посмотреть сообщение
POP3 лишь пример обмена командами.
Дык... Вы определитесь, _что_ именно Вы делаете...
Если _универсальные_ обертки над send/recv это одно и тут как конец приема/передачи можно рассматривать только ошибку или закрытый сокет,
Прием/отправку POP3 это другое (не кто не запрещает использовать ф-ции написанные в 1м случае) и тут в дополнение к общему случаю, как конец приема ответа на команду/приветствие сервера нужно рассматривать в контексте конкретной фазы протокола. Например если после успешной авторизации на NOOP сервер Вам ответит, что-то отличное от "+OK...\n" остается только выругаться и разорвать соединение.
тоже SMTP - третье, HTPP - четвертое
и т.д. и тп.
1
Эксперт С++
 Аватар для Avazart
8483 / 6150 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
18.11.2012, 17:32  [ТС] 17
Ну теперь более или менее понятно нужно отдельно смотреть по каждому протоколу и по ответу... универсально не получится...
На первый взгляд вроде бы всё нормально. Но это не так! В вызове функции recv присутствует параметр MAX_PACKET_SIZE, который определяет длину буфера приёма данных. То есть, Winsock протоколы (TCP/UDP) могут "отправить" пакет размером и 65535 байт. Однако, реальный размер IP пакета, может быть меньше передаваемых данных для конкретного типа сети ( величина MTU - размер наибольшего допустимого кадра в локальной сети или глобальном канале) и поэтому данные фрагментируются (кто хочет - смотрит описание TCP/IP протокола, мы не будем пока углубляться в описание "железного" уровня сети). При этом, фрагментированные данные могут идти с задержками. Какое отношение имеет данная особенность к нашей программе? Всё очень просто. Если мы запросим у удалённого Web-сервера не такой маленький кусочек HTML-кода, как в нашем примере, а немного побольше, то мы получим только первую порцию данных от сервера. Остальная часть данных будет, скорее всего, утеряна. Выход из данного положения очень прост. Он основан на знании принципа работы HTTP и TCP/IP протоколов, плюс некоторых особенностей Winsock. В нашем случае Web-сервер, передав последнюю порцию данных, закроет соединение. А функция recv в таком случае, после получения последнего фрагмента данных, возвращает ноль. Вывод напрашивается сам: мы должны читать входящие данные до тех пор, пока функция recv не вернет ноль.
http://club.shelek.ru/viewart.php?id=37

Вот только HTTP не всегда закрывает соединение...
Тут по заголовку походу надо определять...
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
18.11.2012, 17:44 18
цитата жжот. Человек просто не понимает о чем пишет... Набор умных и правильных слов, но вместе - полный бред.
0
Эксперт С++
 Аватар для Avazart
8483 / 6150 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
18.11.2012, 18:00  [ТС] 19
Ну б сказал нет однозначности...

Правильно ли я понимаю?

1. Если размер буфера меньше размера "пришедшей информации", то recv вызывается несколько раз.
2. Следовательно надо или четко указывать длину буфера так что бы прием шел в один recv, либо
обрабатывать инфу в каждом recv (с анализом заголовка/ответа протокола)

???
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
18.11.2012, 18:25 20
Есть задачи когда нужно смотреть куда-то в полученные (возможно раньше) данные, есть где достаточно "не ошибки" в ф-ции передачи... Т.е. это все абстрактные рассуждения ни о чем.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
18.11.2012, 18:25
Помогаю со студенческими работами здесь

TCP SO_KEEPALIVE и таймаут на прием
Есть клиент, должен посылать несколько запросов подряд, поставил SO_SND+RCVTIMEO, решил добавить ему keep-alive, но с этим проблема: send()...

Работа с UDP, таймаут для setsockopt
Доброго времни суток. Пользуюсь Windows 8.1, Visual Studio 2013, C++. Пытаюсь использовать setsockopt для установки таймаута у recvfrom, в...

Реализовать таймаут PHP pthreads
&lt;?php /** * Author: Abu Ashraf Masnun * URL: http://masnun.me */ //define(&quot;TMT&quot;,3); class WorkerThreads extends Thread ...

Как реализовать таймаут ожидания интента?
у меня есть приложение, пишет кое что на карту mifare classic проблема в том, что все проиходит очень быстро, и прикладывая карту, я...

Как реализовать таймаут на поиск элемента?
Доброго времени суток всем читающим! Помогите, пожалуйста, реализовать таймаут на C#. Занимаюсь задачей автоматизации десктопного...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему

Редактор формул (кликните на картинку в правом углу, чтобы закрыть)
Новые блоги и статьи
Вопросы на собеседовании по Android
mobDevWorks 14.03.2025
По данным статистики, Android занимает более 70% мирового рынка мобильных операционных систем, что делает платформу привлекательной как для начинающих разработчиков, так и для опытных профессионалов. . . .
Лучшие игровые движки для Python
py-thonny 14.03.2025
Python обеспечивает разработчиков игр мощными движками и фреймворками, которые позволяют воплотить практически любую идею — от простой аркады до визуального романа с разветвленным сюжетом. Главное. . .
Бессерверный JavaScript: Разработка масштабируемых API с AWS Lambda
run.dev 14.03.2025
Но что такое бессерверные вычисления на самом деле? По сути, это модель облачных вычислений, где разработчик фокусируется исключительно на создании бизнес-логики, не тратя время на настройку. . .
Безопасность кода в C++26: Менеджеры ресурсов и висячие ссылки
NullReferenced 14.03.2025
C++ всегда был языком, предоставляющим разработчикам большие возможности и гибкость, но вместе с тем требующим ответственности. Одной из самых коварных проблем даже для опытных программистов остаются. . .
smart-agent proper interface settings (2025)
jigi33 14.03.2025
Smart-agent proper interface settings (mart 2025). (see screenshots to look at "Etalon" ARM)
Продвинутые настройки JVM
Javaican 14.03.2025
Стандартные параметры запуска JVM хороши для повседневной разработки, но совершенно недостаточны для высоконагруженных систем. Представьте, что вы запускаете финансовую платформу, обрабатывающую. . .
CI/CD для приложений Java с Azure DevOps и Docker
Mr. Docker 14.03.2025
Разработка современных Java-приложений немыслима без системы непрерывной интеграции и доставки (CI/ CD). Azure DevOps в сочетании с Docker предоставляет мощный инструментарий для создания таких. . .
Разработка на PHP и интернет вещей (IoT)
Jason-Webb 14.03.2025
Интернет вещей (IoT) произвел настоящую революцию в способах взаимодействия устройств с окружающим миром. В эпоху, когда холодильники сами заказывают молоко, а термостаты учатся вашим привычкам,. . .
Node.js 20: Новые возможности и улучшения производительно­сти
Reangularity 14.03.2025
Что же принёс нам релиз Node. js 20? В первую очередь, это существенные улучшения в производительности. Движок V8 получил серьёзные оптимизации, благодаря чему JavaScript-код выполняется заметно. . .
Безопасность кластеров Apache Kafka
Javaican 14.03.2025
Apache Kafka стал одним из ключевых компонентов современных архитектур, обрабатывающих потоки данных в режиме реального времени. Его используют тысячи компаний от стартапов до технологических. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru
Выделить код Копировать код Сохранить код Нормальный размер Увеличенный размер