Форум программистов, компьютерный форум, киберфорум
C++: Сети
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.55/29: Рейтинг темы: голосов - 29, средняя оценка - 4.55
309 / 309 / 215
Регистрация: 24.09.2013
Сообщений: 771
1

Обрыв соединения, TCP

24.11.2014, 21:25. Показов 5335. Ответов 15
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго времени всем.
При реализации TCP сервера и клиента нужно организовать своевременное обнаружение проблем с соединением.
У меня есть следующие варианты:
1. Периодической отправлять/принимать тестовые пакеты.
При таком способе периодическое гуляние тестового мусора по сети снижает её быстродействие.
2. Ловить количество прочитанных с помощью recv байт (если возвращено значение 0, то произошёл обрыв или закрытие сокета)
Этот способ, возможно, правильный, но я не знаю точно, возвращается ли 0 в случае возникновения любых проблем с соединением (если это всё же хороший вариант, то сообщите мне об этом).
3. Читал про keepalive как опция для сокета, стоит ли её использовать и вовремя ли она обнаружит обрыв соединения?
Как всё же лучше организовать обнаружение проблем с соединением? Буду рад услышать и другие варианты, если таковые имеются.
Заранее спасибо.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.11.2014, 21:25
Ответы с готовыми решениями:

Проверка соединения TCP
Привет всем! Пишу MODBUS/TCP-клиент на QNX(POSIX) (есть основной и резервный канал до сервера), с...

Создание последовательного сервера с установлением логического соединения (TCP/IP)
Не могу понять, в чем проблема. Выдает какой-то бред Сервер: #include <WinSock2.h> #include...

Как в клиенте получить локальный IP-адрес TCP-соединения?
Друзья! Кропаю TCP-соединение по книге Криса Касперского "Самоучитель игры на Winsock", так вот,...

Обрыв соединения!
Доброго времени суток уважаемые форумчане!!! Столкнулся с такой проблемой: Приобрёл новенький...

15
Ушел с форума
Эксперт С++
16478 / 7441 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
25.11.2014, 01:27 2
Цитата Сообщение от Pikemaster Посмотреть сообщение
1. Периодической отправлять/принимать тестовые пакеты.
Пакеты ? На TCP ? Интересно было бы посмотреть, как вы это сделаете.

Цитата Сообщение от Pikemaster Посмотреть сообщение
2. Ловить количество прочитанных с помощью recv байт (если возвращено значение 0, то произошёл обрыв или закрытие сокета)
Ну если сервер не проверяет, сколько байт вернула recv - то это какой-то
неправильный, плохой сервер. А вообще, 0 в этом случае означает, что
другая сторона разомкнула свой конец соединения и больше не будет
посылать данных (но пока может их принимать). Ситуация более, чем штатная.

Цитата Сообщение от Pikemaster Посмотреть сообщение
3. Читал про keepalive как опция для сокета, стоит ли её использовать и вовремя ли она обнаружит обрыв соединения?
Стоит или не стоит - это вопрос логики работы приложения.
Но учитывайте, что SO_KEEPALIVE - это дополнительная нагрузка на канал связи.
Так ли это все нужно ? Мне, например, за последние года 3-4 эта опция не
пригодилась ни разу.
0
309 / 309 / 215
Регистрация: 24.09.2013
Сообщений: 771
25.11.2014, 09:50  [ТС] 3
Цитата Сообщение от Убежденный Посмотреть сообщение
Пакеты ? На TCP ? Интересно было бы посмотреть, как вы это сделаете.
Ну само собой это не пакеты в истином смысле Имелась в виду периодическая отправка данных и подтверждение их приёма приёмником.
Убежденный, посоветуйте как же быть тогда.
Может существует какой-нибудь более-менее универсальный вариант проверки соединения?
0
120 / 142 / 46
Регистрация: 31.10.2014
Сообщений: 721
Записей в блоге: 1
25.11.2014, 12:35 4
можете раз в секунду посылать туда-сюда небольшой пакет, и если recv вернул 0 то значит соединение потеряно.
1
309 / 309 / 215
Регистрация: 24.09.2013
Сообщений: 771
25.11.2014, 17:58  [ТС] 5
demmax2004, у меня была такая идея.
Цитата с msdn про возвращаемое recv'ом значение:
If the connection has been gracefully closed, the return value is zero.
Возникает вопрос: равносильно ли "gracefully closed" обрыву соединения любого рода?
0
120 / 142 / 46
Регистрация: 31.10.2014
Сообщений: 721
Записей в блоге: 1
25.11.2014, 18:18 6
Цитата Сообщение от Pikemaster Посмотреть сообщение
равносильно ли "gracefully closed" обрыву соединения любого рода?
Да, конечно
0
Ушел с форума
Эксперт С++
16478 / 7441 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
25.11.2014, 18:52 7
Нет, не равносильно.
"Graceful shutdown" - это плановое закрытие соединения, когда одна из
сторон явно говорит другой: "все, я больше не буду отправлять данные".
Тогда recv на другой стороне возвращает 0. А "connection aborted/refused/etc",
когда recv возвращает -1 - это совсем другое, это признак аварийного
завершения связи.
1
309 / 309 / 215
Регистрация: 24.09.2013
Сообщений: 771
27.11.2014, 00:14  [ТС] 8
Получилось сделать более-менее качественную проверку на обрыв.
Использовал таймер на приём как в этой теме.
https://www.cyberforum.ru/post6609427.html

В цикле передачи данных у меня сервер передаёт какое-то количество байт, а затем ждёт подтверждения приёма путём принятия одного символа (в моём случае символ 'Y') от клиента. В связке с вышеупомянутой функцией получилось что-то вроде этого:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//Server
void set_rcvtimeo(SOCKET socket, unsigned sec = 5, unsigned msec = 0) {
    timeval optval;
    optval.tv_sec  = sec;
    optval.tv_usec = msec;
    setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&optval, sizeof(optval));
}
...
set_rcvtimeo(clientSocket, 10, 1000);
char* answer = (char*)malloc(sizeof(char));
// Цикл передачи данных
while(...)
{       
    answer[0] = 'N';
    if (send(clientSocket, buf, strlen(buf), 0) ...
    if (recv(clientSocket, answer, 1, 0) ...
    if (answer[0] != 'Y') // То время ожидания приёма истекло и клиент до сих пор не прислал данные, т.е. проблемы с соединением.
}
C++
1
2
3
4
5
6
//Client
while(...) {
    if ((bytesReceiving = recv(socket, ... 
    // Делаем что нам нужно 
    if (send(socket, "Y", 1, 0) ... // Отправляем серверу подтверждение того, что клиент всё ещё на связи и заодно даём разрешение серверу отправлять данные снова
}
При таком алгоритме я думаю нет необходимости выставлять таймеры на приём/передачу на клиенте.
Отправка проверочного символа часто используется и просто для "синхронной" работы клиента и сервера, так что здесь эта строка не вводиться по новой, а приобретает вторую роль. (ещё один плюс, который я увидел в этом методе)
Пока что лучшего варианта придумать/найти я не смог.
0
120 / 142 / 46
Регистрация: 31.10.2014
Сообщений: 721
Записей в блоге: 1
27.11.2014, 05:06 9
Отправляй куда больший пакет иначе можешь столкнуться с одной проблемой

Ищи в гугле (на википедии описано): алгоритм Nagle
0
3 / 3 / 3
Регистрация: 28.03.2013
Сообщений: 45
27.11.2014, 22:49 10
Если использовать на пример CSocket, то у него есть функция OnClose() которая срабатывает при обрыве связи.
0
Эксперт С++
8482 / 6149 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.12.2014, 17:19 11
Цитата Сообщение от Pikemaster Посмотреть сообщение
При реализации TCP сервера и клиента нужно организовать своевременное обнаружение проблем с соединением.
Главный вопрос зачем? Что это даст?
0
309 / 309 / 215
Регистрация: 24.09.2013
Сообщений: 771
03.12.2014, 08:55  [ТС] 12
Avazart, есть такая штука как "Требования".
0
Эксперт С++
8482 / 6149 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
03.12.2014, 13:18 13
Pikemaster, Есть такая штука "Обоснование" ну и просто здравый смысл.
0
309 / 309 / 215
Регистрация: 24.09.2013
Сообщений: 771
03.12.2014, 16:45  [ТС] 14
Avazart, у меня нет времени и желания доказывать своему преподавателю ошибочность и абсурдность его же заданий.
Не знаю, что тут может быть непонятно.
0
Эксперт С++
8482 / 6149 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
03.12.2014, 17:05 15
Цитата Сообщение от Pikemaster Посмотреть сообщение
Не знаю, что тут может быть непонятно.
А ну так периодически шли команду NOOP для проверки и если не отправится значит нарушено соединение.
Можно также придумать другую свою команду на которую клиент/сервер должен отвечать "эхом" нечто вроде "пинга" только команда должна содержать уникальный идентификатор типа номер или время запроса что бы можно было отличить этот запрос от предыдущего.
И не морочь голову.
1
309 / 309 / 215
Регистрация: 24.09.2013
Сообщений: 771
03.12.2014, 22:08  [ТС] 16
Avazart, звучит неплохо. Это тоже попробую, спасибо.
0
03.12.2014, 22:08
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
03.12.2014, 22:08
Помогаю со студенческими работами здесь

Обрыв соединения!?
Здравствуйте Такая проблема. Дома 4 ПК подключены к сети через роутер Последнее время стало...

Обрыв соединения
Здраствуйте! Пишу клиент на C# к базе данных(SQL Server 2008), наткнулся на ошибку такого рода (см....

Обрыв сокет соединения
Здравствуйте. Хотелось бы попросить у вас помощи. У меня такая проблема. Есть сервер и клиент....

Обрыв интернет соединения
Всем привет! Я пользуюсь 3джи интернетом, а в роле модема у меня выступает мой моб. Телефон. Но у...


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

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru