Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.79/47: Рейтинг темы: голосов - 47, средняя оценка - 4.79
-1 / 5 / 0
Регистрация: 22.11.2016
Сообщений: 68

Хочу изучить TCP/IP на самом глубоком уровне. Что "внутри" библиотеки ws2_32.dll (winsock)?

22.11.2016, 02:28. Показов 10751. Ответов 48
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Предисловие (можно не читать если не интересно)

Разрабатываю клиент-серверную архитектуру, от которой требуется высочайшая стабильность при любых проблемах с интернетом на клиенте - чтобы клиент работал на всех Windows от XP до 8.1, и x86 и x64, и при критически низкой скорости интернета, и при пропаданиях подключения в любое время и при любой продолжительности.
Соединение должно быть открыто постоянно 24/7 (пока не будет обрыва - тогда оно восстанавливается, причем данные никогда не теряются)
Казалось бы, TCP должен из коробки многое уметь, но я видел то что:
- стандартный winsockовскийKeepAlive работает не всегда, сервер был Win XP x64, одна и та же клиентская программа на C# успешно работала если клиент взять Win 8.1 x64 и не работала если взять Win 7 x86, насколько помню - во втором случае просто не отправлялись пакеты Keep-Alive, а вдруг у меня еще и другие ОС будут, скажем линукс, разве там KeepAlive совместим? сомнения сомнения, вот и решил отказаться от него и делать свою реализацию то есть Heartbeat
- чексумма почему-то не проверяется ни в UDP ни в TCP, ну по крайней мере я вижу то что если отправлять достаточно большой буфер данных, и если уже при отправке на 2 секунды вынуть LAN-кабель (после чего вернуть назад), то пакет с "дыркой" из 0x0 байтов как ни в чем не бывало доходит до принимающего сокета и обрабатывается им, и никаких Exception нигде нету

Я уже частично выработал общий алгоритм:
1)Connect. Он повторяется сколь угодно раз до тех пор пока не перестанет бросать Exception
2)Write обязательно вызывается только один раз для одного сообщения (для одного byte[])
2.1)в этот отправляемый byte[] нужно перед данными еще записать кастомную чексумму (ну раз стандартная не проверяется), и записать размер пакета в байтах чтобы сервер знал сколько выделить памяти для чтения пакета, и в самом начале еще фиксированное число байт для идентификации (потому что не успел я на рабочем сервере запустить очередную версию своей системы для теста, как посыпались пакеты от каких-то неадекватных ботов, что сломало сервер)
3)на сервере Read, у которого обязательно обработка Exception в случае если соединение пропадет уже к моменту вызова Read
3.1)а на случай "дырок" (см. выше) данные нужно читать в цикле, маленькими буферами байт по 10, получая сколько байт по факту считано и тем самым отсеивая "дырки" (это вроде бы получилось сделать)
3.2)затем данные сверяются с чексуммой, если не совпадает то пакет нужно перезапросить то есть в этом случае принимающая и передающая стороны меняются местами
3.2.1)и вообще в любом случае принимающая сторона должна давать ответ об успехе или неудаче (неудача=перезапрос)
4)учесть, что пакет перезапрашивающий данные тоже может дойти не верным, так что все перечисленное к нему тоже применяется, тогда его тоже перезапросить надо, и так до бесконечности пока проблема не исчезнет

Я надеюсь, что хоть этого-то хватит для идеально стабильной работы системы.
Все это буду пошагово тестировать с помощью тротлинга (программ, которые замедляют скорость интернета) и с помощью ручного и программного обрыва соединения.

Но надежды это хорошо, а я бы хотел иметь знания, достоверно изучить тему до уровня Tx/Rx которые в сетевом кабеле, увидеть все своими глазами, это и в будущем пригодится, с железом вроде различных микроконтроллеров (и даже "заказных" микросхем типа черных "капель"!) придется иметь тесные отношения.

И вот вопросы:

1) что "внутри" ws2_32.dll?
насколько знаю, в Windows есть сетевой драйвер - это служба, он напрямую работает с Tx/Rx (или как-то через BIOS? UEFI?), а с другой стороны есть ws2_32, который работает с драйвером.
по каком "протоколу", каким способом ws2_32 связан с драйвером? это случайно не ZwOpenFile (часто применяемый для связи с драйверами)?

2) возможно ли работать с этим драйвером напрямую без ws2_32?
не пугайтесь - этого не будет в продакшн, просто исследование

3) возможно ли спуститься еще глубже драйвера и напрямую работать с Tx/Rx/BIOS/UEFI? опять же в продакшне этого не будет, тем более это уже даже не user-mode, а нечто близкое к нулевому кольцу, вопрос только в том - насколько сложно, сколько вообще времени займет это исследование?

Внимание!
P.S. Вопрос не по сетям в целом, а только по ОС Windows, я понимаю то что можно и линукс (андроид) сюда подключить, но
если я буду одновременно две ОС исследовать, то мне уж точно никакого времени не хватит
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
22.11.2016, 02:28
Ответы с готовыми решениями:

Сформировать N-уровневый вложенный список, элементом которого на самом глубоком уровне является число N
Мужики помогите, задание программы- Формировать N-уровневый вложенный список, элементом которого на самом глубоком уровне является число N ...

Создает на n - уровне вложенный список, элементом которого на самом нижнем уровне является n
Я решил задачу так: CL-USER 1 > (defun f (l n) (cond (( eq n 0) l) ((null l) (f (list n) (- n 1))) (t (f (cons...

точка входа в процедуру inet_pton не найдена в библиотеке dll ws2_32.dll
Привет! Почему когда я запускаю игру у меня появляется ошибка "точка входа в процедуру inet_pton не найдена в библиотеке dll...

48
-1 / 5 / 0
Регистрация: 22.11.2016
Сообщений: 68
09.12.2016, 07:49  [ТС]
Студворк — интернет-сервис помощи студентам
Убежденный,
Ну а "дырок" посреди TCP-потока не может быть. Все-таки это протокол, который гарантирует
доставку данных в правильном порядке и следит за их целостностью.
Каюсь, с "дырками" посреди потока я попутал, смоделировать такую ситуацию не получается.
Зато вот возникла другая проблема, пожалуй, более серьезная, чем "дырки".

Итак, есть сервер и клиент, и все те же требования к суперпуперстабильности.
Вот я выдергиваю сетевой кабель у клиента. И тут же клиент хочет что-то отправить серверу через write (send).
Клиент вызывает write и... тишина!
Просто ничего не происходит. write/send не выкидывает код ошибки, не создает к Exceptionов и т.п. И в то же время если тут же воткнуть кабель, то данные так и не приходят. То есть они просто теряются без всякого уведомления для отправляющей стороны (клиента).
Я повторно вызываю write/send - та же история.
Но, что интересно, если выждать с пол-минуты после обрыва и только потом вызвать write/send, то Exception уже выпадет.

Собственно, вопрос - что делать, чтобы сообщения не терялись?
Я бы мог после write/send просто сразу вызывать read, то есть читать ответ сервера, и это уже привело бы к Exception, но дело в том, что помимо write/send у меня в отдельном потоке всегда крутится while (true) { read } так как клиент должен в любой момент быть готов к командам от сервера (на сервере, к слову, тоже цикл - уж так надо), поэтому я не могу вызвать read в другом месте (там, где write) - это запутает код, а тот read который в цикле - в это время находится в режиме ожидания и при обрыве кабеля он же тоже не вылетит с Exception, ведь так?

Есть разные идеи:
- использовать таки пару Write-Read, но Read не простой, а peek
- перед Write проверять есть ли соединение, делать это не средствами TCP, а с помощью функций WinAPI, которые проверяют есть ли сеть
- перед Write проверять есть ли соединение, делать это средствами TCP (какими?)
- пинг
- использовать KeepAlive и select (poll), но не совсем понимаю, как это мне поможет, к тому же я бы хотел обойтись без keepalive и реализовать heartbeat, как быть в этом случае?
- и другие, сейчас не вспомню, так как устал

Как правильнее?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
09.12.2016, 09:59
hemoa, а про какой Exception ты говоришь?
send/recv, если мы про WinSock, вообще никаких исключений не кидают,
это же сишный API...
0
-1 / 5 / 0
Регистрация: 22.11.2016
Сообщений: 68
09.12.2016, 12:11  [ТС]
Убежденный, про сишарповский, про дельфийский, и в C# и в Delphi одинаково, следовательно, проблема не в них.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
09.12.2016, 13:51
Цитата Сообщение от hemoa Посмотреть сообщение
Клиент вызывает write и... тишина!
Просто ничего не происходит. write/send не выкидывает код ошибки, не создает к Exceptionов и т.п. И в то же время если тут же воткнуть кабель, то данные так и не приходят. То есть они просто теряются без всякого уведомления для отправляющей стороны (клиента).
Я повторно вызываю write/send - та же история.
Но, что интересно, если выждать с пол-минуты после обрыва и только потом вызвать write/send, то Exception уже выпадет.
Собственно, вопрос - что делать, чтобы сообщения не терялись?
Успешный send говорит лишь о том, что данные были отправлены. То есть, например, они
были записаны в какой-то внутренний буфер сетевого стека и система отправляет их по сети.
Или отправит чуть позднее. Но send ничего не говорит о том, дошли ли данные до адресата,
все ли данные он успел прочесть и т.д.

Представь такую ситуацию: ты вызвал send, она вернула N, т.е. N байт положили в
системный буфер. И как раз в этот момент, когда данные не успели еще никуда уйти
по сети, рубануло свет и компьютер отключился.

Send лишь может гарантировать (для TCP), что данные из следующего send не
перемешаются с предыдущим и если был обрыв, то другая сторона больше никаких
данных не получит, т.к. поток TCP уже прерван.
0
-1 / 5 / 0
Регистрация: 22.11.2016
Сообщений: 68
09.12.2016, 14:26  [ТС]
Убежденный,
Цитата Сообщение от Убежденный Посмотреть сообщение
Представь такую ситуацию: ты вызвал send, она вернула N, т.е. N байт положили в
системный буфер. И как раз в этот момент, когда данные не успели еще никуда уйти
по сети, рубануло свет и компьютер отключился.
А как же ACK, который возвращается принимающей стороной после получения сообщения?
В описанной ситуации он не придет. Почему ОС не проверяет, пришел ли он?

Еще непонятки с таймаутами.
Если я для read поставлю таймаут 1 мсек, то при обрыве read начнет быстрее возвращать исключение, чем если не ставить. Однако тогда и без обрыва read тоже будет "фейлить", если отправляющая сторона задержится на 1 мсек.
А по умолчанию он "фейлит" только при обрыве, а иначе read держится в ожидании сколь угодно долго (не считая ограничения в 2 часа по неактивности).
Вопрос: что же за "волшебный" таймаут стоит по умолчанию?

если был обрыв, то другая сторона больше никаких
данных не получит, т.к. поток TCP уже прерван.
В смысле?
Если я кабель верну на место после обрыва и нескольких send в "черную дыру", и затем снова вызову send, то он сработает, как будто бы обрыва не было.

Добавлено через 3 минуты
Еще вот все думаю о протоколе SCTP, он же более совершенен, чем TCP, почему он не получил распространения, не поддерживается Windows, хотя вроде широко поддерживается в Linux (но, впрочем, и там не распространен)?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
09.12.2016, 15:36
Цитата Сообщение от hemoa Посмотреть сообщение
А как же ACK, который возвращается принимающей стороной после получения сообщения?
В описанной ситуации он не придет. Почему ОС не проверяет, пришел ли он?
Проверяет. Но система не будет бесконечно ждать подтверждения.
Как только истекает определенный таймаут и число попыток повторной отправки
(см. TCP ACK, TCP Retransmission и т.д.) - соединение считается разорванным.

Цитата Сообщение от hemoa Посмотреть сообщение
Вопрос: что же за "волшебный" таймаут стоит по умолчанию?
Например:

How to modify the TCP/IP maximum retransmission time-out
https://support.microsoft.com/en-us/kb/170359
0
-1 / 5 / 0
Регистрация: 22.11.2016
Сообщений: 68
09.12.2016, 15:48  [ТС]
Убежденный,
Как-то ты все вокруг да около.
Как только истекает определенный таймаут и число попыток повторной отправки
(см. TCP ACK, TCP Retransmission и т.д.) - соединение считается разорванным.
И что дальше? Задается LastError? Или это проявляется только при следующем вызове?
В действительности, я не вижу ничего этого, зато вижу странные 30 секунд, через которые Write и в C# и в Delphi уже выдает исключение, если обрыв так и не исчез. Судя по наблюдениям, неважно, вызывал ли я send в течение этих 30 секунд или я его впервые вызываю только через эти 30.
Где-то на форуме один человек связывал эти 30 секунд с то ли интервалом, то ли таймаутом у Keep-alive, но причем тут Keep-alive, он у меня вообще не включен, да и чем он отличается от обычной отправки сообщений, чтобы вести себя иначе ?

Да я уже примерно знаю что можно сделать, выше жаловался что второй Read вне "основного" цикла запутает код, но сейчас я бы и это как-нибудь пережил, но мне надо точно знать что и как, зависит ли от версии винды, разрядности, от сетевой карты в компе, от того Wi-Fi или LAN.
Ибо я уже начинаю реально бояться TCP, он и раньше мне мозг выносил (я один такой? другие просто "не парятся" и у них реализация рандомно получается успешной, а мне вот не повезло? у меня мозг такой особый, что несмотря на успехи скажем в реверсинге, я дебил в TCP?), но сейчас я еще и реально боюсь что-то делать и выкладывать на реальный сервер и рассылать по реальным клиентам, потому что информация по TCP в интернете очень отрывочная, и мнения с форумов противоречат друг другу.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
09.12.2016, 16:28
Цитата Сообщение от hemoa Посмотреть сообщение
Как-то ты все вокруг да около.
Я просто не до конца понимаю, что именно тебя не устраивает в TCP и
какого поведения ты хочешь от него добиться.

TCP не может тебе сразу сообщать, что был разрыв связи.
Send/recv - это асинхронные по своей природе операции.
Каждая порция данных бьется на сегменты, каждый сегмент может
отправляться повторно несколько раз, а еще данные проходят
через фаерволы, спам-фильтры, прокси-серверы...

Допустим, при отправке очередного TCP-сегмента ответ не пришел.
Система пытается отправить его еще раз и еще. Она "ничего не знает" о
том, что на другом конце провода обрыв, например.

И только когда установлено (по таймауту и лимиту попыток), что данные
на тот конец не доходят, соединение считается разорванным.
Это значит, что очередной send или recv будут возвращать ошибку.
Какую именно - зависит от реализации TCP.
0
-1 / 5 / 0
Регистрация: 22.11.2016
Сообщений: 68
09.12.2016, 16:50  [ТС]
Убежденный,
Я просто не до конца понимаю, что именно тебя не устраивает в TCP
Какой смысл быть недовольным, если все равно ничего не изменишь? Устраивает-неустраивает здесь некорректно.
Я просто не могу его в полной мере понять, поэтому не могу гарантировать человеку, что я все сделал правильно и надо бы выплатить солидную часть всего бюджета проекта.

И только когда установлено (по таймауту и лимиту попыток), что данные
на тот конец не доходят, соединение считается разорванным.
Еще раз, нету никаких попыток, в том числе keep-alive не включен.
Но если прошло 30 сек после обрыва - то у клиента вызов send приводит к ошибке, даже если это первый вызов с момента подключения клиента.
А не прошло - не приводит.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
09.12.2016, 16:59
Цитата Сообщение от hemoa Посмотреть сообщение
Еще раз, нету никаких попыток, в том числе keep-alive не включен.
Я имел в виду TCP Retransmission.
0
-1 / 5 / 0
Регистрация: 22.11.2016
Сообщений: 68
09.12.2016, 17:12  [ТС]
Убежденный, а причем тут 30 секунд ты объяснить не можешь. Настаиваешь, что и нету этого. Типа галлюцинации у меня, или это частная проблема сразу и .NET и Indy (Delphi).

Lisp
1
(println "Ну ничего страшного, пойду немножко другой язык попробую.")
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
09.12.2016, 17:15
Цитата Сообщение от hemoa Посмотреть сообщение
Убежденный, а причем тут 30 секунд ты объяснить не можешь.
Не могу.
Я пользуюсь TCP через тот public API, который он предоставляет, а в
детали реализации не лезу. Лезу только тогда, когда поведение меня
не устраивает. Но такое бывает чрезвычайно редко.

Цитата Сообщение от hemoa Посмотреть сообщение
Настаиваешь, что и нету этого. Типа галлюцинации у меня, или это частная проблема сразу и .NET и Indy (Delphi).
Я такого бреда нигде не писал.
0
-1 / 5 / 0
Регистрация: 22.11.2016
Сообщений: 68
09.12.2016, 17:32  [ТС]
Убежденный,
Я пользуюсь TCP через тот public API
И в нем нету вышеописанного с 30 секундами? Ну ОК, залезу опять в Си. Геморрой, а что делать. Хоть смогу тебе продемонстрировать, протестишь у себя.
А пока другой вопрос, касательно не обрыва, а штатного отключения отправляющей стороны - FIN и RST.
Так вот, если на сервере recv возвращает 0 - значит ли это, что клиент отвалился и что уже не надо с ним ничего делать, лишь ждать нового его подключения? Или же нет?
Просто у меня на сервере while (true) { ...recv...} и при одном из флагов, отправленном со стороны клиента, (по-моему FIN), цикл на сервере начинает зацикливаться, при этом recv возвращает 0, и снова 0, и снова.
Я думаю при 0 просто делать break, поскольку с этим клиентом уже сервер не может ничего не сделать, 0 значит он отвалился. Но всегда ли это так?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
09.12.2016, 18:10
recv == 0 означает, что та сторона больше не будет ничего присылать.
Но при этом ей все еще можно отправлять данные.
Обычно recv == 0 получается, когда на той стороне кто-то делает shutdown(Sock, SD_SEND).
"Отвалился" здесь не совсем точная формулировка. Правильнее было бы сказать,
что клиент закрыл свой конец соединения для отправки. Это часть т.н. Graceful Shutdown.
1
-1 / 5 / 0
Регистрация: 22.11.2016
Сообщений: 68
10.12.2016, 10:50  [ТС]
Убежденный,
В общем вышеописанную проблему с "черной дырой" я решил, но частично.
Вот мой алгоритм:
0) На клиенте обрывается кабель
1) Сразу после этого клиент вызывает send - отправляет серверу очередной heartbeat, то есть пустое сообщение, специально предназначенное для этой цели
2) А тем временем на клиенте еще есть параллельный поток, в котором вышеописанный цикл, и в нем в это время висит recv в режиме ожидания
3) Проходят эти самые 30 секунд, и если обрыв так и не пропадет, то recv приведет к Exception, что в C# что в Delphi.
4) Обрыв выявлен. PROFIT. Можно пробовать подключаться к серверу повторно.

И этот алгоритм реально работает на клиенте.
Но и серверу тоже неплохо бы знать об обрыве.
Однако на сервере почему-то тот же алгоритм работает иначе, и Exception по-моему происходит не через 30 секунд, а после того как обрыв исчезнет

В чем может быть причина?
Может быть, дело в том, что обрыв кабеля по-прежнему у клиента, а этот алгоритм, будучи на сервере, выявит только обрыв кабеля на сервере? Или неважно на каком участке обрыв?
Опять же - все вокруг трубят о том, что на уровне TCP почти ничем сервер от клиента не отличается, но вот оно различие.

Есть и другие способы, например таймаут, который бы просто ждал N секунд, и если recv все еще висит - то обрыв выявлен, но это мне не нравится как-то...
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
11.12.2016, 09:34
Цитата Сообщение от hemoa Посмотреть сообщение
В общем вышеописанную проблему с "черной дырой" я решил, но частично.
Вот мой алгоритм:
0) На клиенте обрывается кабель
1) Сразу после этого клиент вызывает send - отправляет серверу очередной heartbeat, то есть пустое сообщение, специально предназначенное для этой цели
2) А тем временем на клиенте еще есть параллельный поток, в котором вышеописанный цикл, и в нем в это время висит recv в режиме ожидания
3) Проходят эти самые 30 секунд, и если обрыв так и не пропадет, то recv приведет к Exception, что в C# что в Delphi.
4) Обрыв выявлен. PROFIT. Можно пробовать подключаться к серверу повторно.
Все это, конечно, здорово, вот только теперь количество подключений на
сервер возрастает в два раза. И если раньше, к примеру, твой сервер мог держать
предел в 1000 соединений (условно), то теперь только 500...

Цитата Сообщение от hemoa Посмотреть сообщение
И этот алгоритм реально работает на клиенте.
Но и серверу тоже неплохо бы знать об обрыве.
Однако на сервере почему-то тот же алгоритм работает иначе, и Exception по-моему происходит не через 30 секунд, а после того как обрыв исчезнет
В чем может быть причина?
Может быть, дело в том, что обрыв кабеля по-прежнему у клиента, а этот алгоритм, будучи на сервере, выявит только обрыв кабеля на сервере? Или неважно на каком участке обрыв?
Опять же - все вокруг трубят о том, что на уровне TCP почти ничем сервер от клиента не отличается, но вот оно различие.
Расскажи, почему ты считаешь, что ситуация с детектом обрыва соединения не сразу, а
спустя некоторое время, ухудшает надежность связи или неприемлема?

Давай мысленно перенесем описанную тобой ситуацию на HTTP.

Итак, клиент подключился к серверу и отправляет ему стандартный HTTP-запрос длиной,
скажем, в 456 байт. Т.е. клиент выполнил send, send вернул 456, что означает,
что все данные отправлены. Теперь клиент вызывает recv, ожидая ответ сервера.
В это время данные пришли на сервер, но не все. Пришло, скажем, 123 байт (только
первый TCP-сегмент). Второй и следующий сегменты не дошли - где-то обрыв.
TCP-подсистема на клиенте несколько раз в течение определенного времени пыталась
доставить данные сегменты повторно, но ей это не удалось. Следовательно, recv
на клиенте, сразу или спустя некоторое время, уже вернет -1 (ошибка) - признак
того, что соединение было разорвано.

Сервер прочел 123 байта. Увидел, что пришел не весь запрос и вызывает recv
еще раз. Спустя некоторое время его recv тоже возвращает ошибку -1, что для
сервера также недвусмысленно означает разрыв соединения.

Все, браузер пишет клиенту что-то типа: "проблемы с соединением, попробуйте
повторить запрос позже". Оба конца соединения закрываются.

Итог: соединение разорвано, на сервер пришла только часть данных.
Но при этом нет такого, что пришли заведомо "битые" данные или данные были
доставлены не в том порядке. То есть, оба участника HTTP-сессии отреагировали
адекватно на разрыв соединения.
0
-1 / 5 / 0
Регистрация: 22.11.2016
Сообщений: 68
11.12.2016, 10:25  [ТС]
Убежденный,
Все это, конечно, здорово, вот только теперь количество подключений на
сервер возрастает в два раза. И если раньше, к примеру, твой сервер мог держать
предел в 1000 соединений (условно), то теперь только 500...
Не понял. Каких подключений? Новое подключение будет создаваться только после обрыва, то есть в пункте 4.
При этом предыдущее подключение на сервере удалится - вместе с удалением потока и всеми требуемыми close/shutdown/..., во всяком случае, оно должно удалиться, вот для этого я и хочу реализовать этот механизм на сервере симметрично клиенту.

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

Давай мысленно перенесем описанную тобой ситуацию на HTTP.
У меня тут не HTTP, у меня нечто больше похожее на мессенджер, чат. В мессенджерах же моментально отображается что такой-то клиент отключился, значит, сервер как-то узнает об этом.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
11.12.2016, 10:33
Цитата Сообщение от hemoa Посмотреть сообщение
Не понял. Каких подключений?
Вот этих:

Цитата Сообщение от hemoa Посмотреть сообщение
2) А тем временем на клиенте еще есть параллельный поток, в котором вышеописанный цикл, и в нем в это время висит recv в режиме ожидания
Или ты хочешь одновременно вызывать send и recv на одном сокете?

Цитата Сообщение от hemoa Посмотреть сообщение
Ну, сервер должен как можно быстрее узнавать об обрыве соединения с клиентом, потому что там есть админка, в которой сервер выдает список доступных клиентов, важна актуальность этого списка.
Админ будет заходить в список и отправлять одному из клиентов команду, которую он должен выполнить и вернуть ответ, а пока получается что эта команда просто зависнет до тех пор, пока обрыв не восстановится, сервер узнает об обрыве только когда обрыв восстановится (см предыдущее сообщение, пока из нескольких наблюдений именно такой вывод), а я хз когда он восстановится, может через полминуты, может через полдня.
А почему бы просто не использовать таймауты?
В WinSock ведь можно работать с сокетами асинхронно.
Например, я могу отправить команду recv (точнее, WSARecv), а затем в этом же
потоке ждать, что наступит раньше - завершение операции или срабатывание
по таймауту. Если сработал таймаут - закрываем сокет и пишем "error, код такой-то".
0
-1 / 5 / 0
Регистрация: 22.11.2016
Сообщений: 68
11.12.2016, 11:10  [ТС]
Убежденный,
Или ты хочешь одновременно вызывать send и recv на одном сокете?
Естественно. В чем проблема-то?
В C# точно ни в чем, создаю поток, в нем крутится Read (recv), в другом потоке Write heartbeat, в третьем, четвертом, десятом - все остальные Write, сколько бы их ни было.
На сервере - симметрично, то есть то же самое, на каждого клиента.

Где-то писали, что так якобынельзя, что мол TCP нужно использовать по принципу "walkie-talkie", то есть якобы нельзя сразу и recv держать в режиме ожидания и send в другом потоке вызывать, но мне это нужно по условию задачи (которое уже довольно подробно тебе описал), создавать несколько сокетов на одного клиента считаю абсурдом, и нужды в этом не вижу, все вроде нормально работает, кроме описанной вчера проблемы когда пытаюсь реализовать аналогичное на сервере.

А почему бы просто не использовать таймауты?
В WinSock ведь можно работать с сокетами асинхронно.
Например, я могу отправить команду recv (точнее, WSARecv), а затем в этом же
потоке ждать, что наступит раньше - завершение операции или срабатывание
по таймауту. Если сработал таймаут - закрываем сокет и пишем "error, код такой-то".
О каком таймауте речь и где его задавать?
Есть большое подозрение, что на клиенте такой таймаут получается 30 сек (промежуток между send в "черную дыру" и вылетом ждущего recv в другом потоке) А на сервере этот таймаут почему-то "волшебный", бесконечный что ли.
Мне бы разобраться, как его задавать. А то меня еще пугают настройки в реестре, вдруг на каком-то клиенте или сервере они будут изменены и будет работать иначе, чтобы этого не было мне следует "override"ить их в своих клиентах и сервере.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
11.12.2016, 12:34
Цитата Сообщение от hemoa Посмотреть сообщение
Где-то писали, что так якобынельзя, что мол TCP нужно использовать по принципу "walkie-talkie", то есть якобы нельзя сразу и recv держать в режиме ожидания и send в другом потоке вызывать
В WinSock можно. Так работают прокси-серверы, например.
А вот делать параллельно send-send или recv-recv на одном сокете точно нельзя.
Не технически, а в том плане, что данные в итоге могут "перемешаться".

Цитата Сообщение от hemoa Посмотреть сообщение
О каком таймауте речь и где его задавать?
Я создаю сокет в асинхронном режиме - WSASocket. Делаю коннект на нужный адрес-порт.
Далее вызываю WSASend (или WSARecv - не важно). Обычно функция возвращает управление
немедленно, при этом в WSAGetLastError == WSA_IO_PENDING, т.е. передача началась.
Далее делается WaitForSingleObject или WaitForMultipleObjects с указанием желаемого таймаута, в
списке объектов ожидания которой должен быть указан хэндл сокета. Далее развитие событий такое:
либо Wait-функция вернет STATUS_TIMEOUT, т.е. истекло время ожидания, а операция так и
не была выполнена, либо она вернет WAIT_OBJECT_X, т.е. операция завершена, можно
получать ее статус и прочие параметры.

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

Никакие настройки реестра на этот таймаут влиять не будут.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
11.12.2016, 12:34

Проверка данных внутри библиотеки dll
Есть библиотека, в которой хранятся различные методы. Для простоты, пусть в этой библиотеке есть класс, содержащий метод, который берет из...

Как изучить WinSock
Есть ли годная литература для c++?

Подключение библиотеки импорта Ws2_32.lib
Добрый вечер, при подключение библиотеки импорта Ws2_32.lib и соответственно заголовочного файла "Winsock2.h" сыпятся ошибки. ...

Хук на ws2_32.dll
День добрый всем. Нужна помощь коллективного разума. Пишу парсер трафика онлайн игры. Поставил хук на прием данных сокета (recv) по...

Сокеты через Ws2_32.dll
Есть ли у кого работающий пример гет запроса на какой-нибудь сайт ? В нэте всё в DEV-C++ не работает,а знаний что-либо исправить не...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
сукцессия 29. Переход от одних деревьев на другие делать более или менее вероятностным?
anaschu 12.07.2026
Насколько смена типов микоризы — исключительное событие в двухвековой сукцессии? Оценка вероятности в пространстве параметров В текущей версии модели успешно реализован ключевой механизм. . .
сукцессия 27. Думаю, как переделывать уже написанную статью с планами на сукцессию.
anaschu 12.07.2026
Анализ соответствия модели требованиям Реализованные компоненты: Механизм закисления почвы через протонную помпу Конкуренция между типами микориз pH как триггер сукцессии C/ P соотношение. . .
Сукцессия 26. Мат модель создана.
anaschu 12.07.2026
Модель смены растительных сукцессий посредством управления грибами работает внутри небольшой ячейки почвы, восстанавливающейся после пожара, где ненадолго бывшее царство хвойных снова захватили. . .
Решил проблему с ошибкой пагинации сообщений с сервера на алгоритме обхода дерева "Эстафета хвоста".
Hrethgir 12.07.2026
Проблема была в том, что удалялась именно новая кнопка, а не старая. Ни один ИИ не обнаружил это, а сам я смог только когда с работой стало попроще и когда заставил работать будущее автономное. . .
сукцессия 25. Хронология ошибок
anaschu 12.07.2026
# От 50-тонного гриба до устойчивого леса: хроника ошибок при построении модели вековой сукцессии микоризы ## О чём эта статья В процессе построения ОДУ-модели (система дифференциальных. . .
сукцессия 24. Промежуточное общее описание модели
anaschu 12.07.2026
Хендофф: модель АМ→ЭКМ сукцессии микоризы (ризосфера, 50 лет) Содержание проекта Симуляция вековой (50 лет) экологической сукцессии в почве леса Основные участники: АМ-гриб, ЭКМ-гриб,. . .
сукцессия 23. Более физиологичная физиология, более экологичная экология, более диффурные диффуры.
anaschu 12.07.2026
Что реально нашли и починили за эти 5 часов Правило Линдемана (КПД конверсии сахара в тело, kEff) — раньше 100% полученного углерода шло прямо в биомассу гриба; теперь только kEff=0. 5 (после. . .
сукцессия 22. От артефактов к физиологии: калибровка агентной модели грибной сукцессии для воспроизведения сезонной динамики и pH-плато
anaschu 11.07.2026
Аннотация В данной работе представлена калибровка агентной модели динамики грибных сообществ (fungal-succession), направленная на устранение нефизичных артефактов (коллапс биомассы, мгновенное. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru