Об игре
Новости
Войти
Регистрация
Рейтинг
Форум
19:59
4339
 online
Требуется авторизация
Вы не авторизованы
   Форумы-->Форум для внеигровых тем-->

АвторПередача информации по TCP используя winsock2 - нужна помощь
Хотелось бы попросить помощи. Если кто разбираешься в вопросах сетевой передачи информации по протоколу TCP используя winsock2.

Никак не могу найти информацию о том, каким образом можно констатировать то, что посланная мной информация по сети дошла до адресата.

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

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

Ну вот а как же проверить, доведение информации инструментами предназначенными для сетевого программирования я так и не понял.

Не,... тут как бы не вопрос - всегда можно поверх TCP написать свой протокольчик, который будет за этим следить, но это изврат какой-то на мой взгляд, так как в таком случае я не смогу общаться с уже существующими серверами работающими по протоколу TCP, которые естественно не будут ничего знать о моём протоколе)))

В общем если может кто - хелп плиз)))
что посланная мной информация по сети дошла до адресата.
Спросить у него не?
для Zael_Hell:
Спросить у него не?
Ну и как у него это спросить используя winsock2?
для ChinaNoDollar:
А почему именно winsock? Ты уверен, что обратная связь вообще предусмотрена средствами протокола, а не реализуется надстройками?
для ChinaNoDollar:
Ну и как у него это спросить используя winsock2?
А позвонить или спросить в реале? Неужно уже приросли к тому на чём сидите?
для BlackBaron:
А почему именно winsock?
А ручками совершенно не хочется формировать TCP пакеты и общаться с сетевой картой, так как скорее всего эти чисто организационные вопросы уже давно решены и предоставлены нам в виде того же winsock.

Ты уверен, что обратная связь вообще предусмотрена средствами протокола, а не реализуется надстройками?

Я уверен в том, что написать надстройку над TCP всегда можно и там пожалуйста делай что хочешь, проверяй что хочешь и когда хочешь. Но я же использую протокол с установлением соединения, а значит все должно быть доступно для анализа, как я понимаю.

Обратная связь по любому есть, так как протокол ведь не пришедшие(затерявшиеся) пакеты досылает повторно, а значит он узнает о том, что они потерялись и шлет их заново. Иначе зачем были бы нужны контрольные суммы и т.д. и т.п. в протоколе TCP.
Иначе зачем были бы нужны контрольные суммы
Ну это-то понятно - чтобы на том конце могли верифицировать целостность доставки, а вот всё остальное... хз, не могу подсказать, не настолько хорошо знаю нижний уровень(
для BlackBaron:
Ну это-то понятно - чтобы на том конце могли верифицировать целостность доставки, а вот всё остальное... хз, не могу подсказать, не настолько хорошо знаю нижний уровень(

Просто, реально пока не понимаю как писать программу дальше, если я не могу определить дошла информация до адресата или надо заново её слать.
И мне не видется приемлимым искать способы проверки текущего состояния соединения типа команды ping, которая на момент отработки может вернуть и положительный результат, а вот на момент выполнения функции отправки уже реально соединения может и не быть(((
для ChinaNoDollar:
НУ а что тебе мешает написать свою маленькую процедурку проверки?
для BlackBaron:
НУ а что тебе мешает написать свою маленькую процедурку проверки?

Так я бы с радостью написал такую, но не знаю куда надо посмотреть, чтобы сделать тот или иной вывод. Собственно в этом и проблема)))
Ездил в Библио Глобус, но ни одной книги подходящей не нашел((( Может еще куда надо съездить, но хз...В книгах дрянь какая-то общая написана в общей своей массе(((

Мне бы книгу, в которой полностью описана модель работы например по протоколу TCP. Где описаны все флажечки, переменные, которые выставляются при том или ином сетевом событии. Где есть описание всех функций для получения всех этих флажков, переменных ...

Не нашел ни одной такой книги пока что(((
Вот например нашел следующее описание протокола TCP:

TCP/IP представляет собой комбинацию двух уровней, TCP и IP. IP – протокол третьего уровня – обеспечивает наилучшую, но не гарантированную доставку данных через сеть. TCP – протокол четвертого уровня – позволяет эту гарантию обеспечить. Поэтому совместно они могут предоставить большее количество сервисов.

Работа по TCP-протоколу начинается с установления соединения. Два компьютера (один из них инициатор соединения, второй – принимающий) обмениваются специальными пакетами в три этапа. Условно их можно назвать "запрос", "подтверждение" и "подтверждение на подтверждение". Такая процедура необходима, чтобы при получении какого-нибудь старого пакета (например, делается вторая попытка установить соединение) не возникало никаких неоднозначностей.

После успешного установления соединения участники могут начать обмениваться данными. Рассмотрим пример HTTP-сервера, который отправляет HTML-страницу клиенту. Текст может быть слишком длинным, чтобы уместиться в один пакет, поэтому первая задача уровня TCP – разбить сообщение на несколько пакетов, а на стороне отправителя – собрать их опять в единое целое. Поскольку очередность пакетов несомненно важна, каждый получает порядковый номер.

Следующая задача протокола – обеспечить гарантированную доставку. Делается это с помощью следующей процедуры. Отправитель посылает пакет с номером n и начинает ждать. Получатель в случае успешного прихода пакета n, отправляет подтверждение о получении ("квитанцию"), в котором также указывает номер n. Если отправитель в течение определеннного времени (тайм-аута) не получает подтверждения, он считает пакет n потерянным и отсылает его еще раз.

Разумеется, отправителю неэффективно просто ждать, пока получатель получит и обработает каждый пакет по одному. Поэтому процедура усложняется, вводится специальное понятие – "окно" (window). Окно имеет некоторый размер, предположим, 10. Это означает, что передача начинается с отсылки 10 первых пакетов. Получатель может принять их не в том порядке, в каком они были отосланы. Тем не менее, на каждый успешно полученный пакет отсылается подтверждение с указанием номера такого пакета. Если отправитель отослал уже все 10 пакетов, но квитанция о получении пакета 1 так и не пришла, то передача приостанавливается, а по прошествии тайм-аута первый пакет считается потерянным и пересылается еще раз. Если же подтверждения приходят регулярно, то отправляются новые пакеты, но не более 10 единовременно.

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

Взял с сайта http://www.intuit.ru/department/pl/javapl/16/3.html

И я склонен думать именно также, про протокол TCP, который присылает подтверждающие квитанции пакетов.
Опять ты?)))

TCP/IP представляет собой комбинацию двух уровней
Что за бред? TCP/IP - это эталонный стек протоколов. И в нём 4 уровня.

Я смог нагуглить 2 решения. Правда проверить их тебе самому придётся ;)

Решение 1. Когда ты отправляешь пакеты, не факт, что они отправляются сразу. Сообщение записывается в буфер, отправляется когда-то потом, поэтому при проверке ошибки сразу после отправки ты ничего не увидшь.
Исходя из этого, можно сделать размер отправляющего буфера 0, поэтому все сообщения будут уходить сразу. И если при этом возникает ошибка, он её сразу и выдаёт.

Решение 2. Перед отправкой определять - жив ли сокет. Делается это (под виндой) так - для сокета вызывается select на чтение с нулевым таймаутом. Если select вернул 1, то смотрим - сколько данных доступно на чтение из сокета. Если 0 - то соединение разорвалось. Этот трюк подсмотрен где-то в MSDN.

Попробуй, может чего и сработает.
для FireSwarm:
Решение 1

В общем идея понятная, но по моему она ламерская чуток) А если пинг до адресата секунда или поболее и отпарвляться будет по одному пакету? Фигня какая-то выходит!

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

Че-то как-то такая идея меня опять же не радует совсем и она не может быть правильной!

Да и более того, я опять не знаю как узнать когда send реально отработала ;)

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

Вот в эту сторону возможно надо копать:
http://vsokovikov.narod.ru/New_MSDN_API/Menage_files/fn_getqueuedcompletionstatus.htm

Я на раскопки ;)
winsock2
Победитьносок2?
для FireSwarm:
Не, чё-то не прокатывает предложенный тобой вариант номер один. Устанавливаю исходящий буфер равным нулю:
....int buffLen=0;
....err = setsockopt(sockControl, SOL_SOCKET, SO_SNDBUF, (char*)&buffLen, sizeof(buffLen));
Пробую и нифига.

Попробовал и входящий буфер в ноль выставить вмете с исходящим:
err = setsockopt(sockControl, SOL_SOCKET, SO_RCVBUF, (char*)&buffLen, sizeof(buffLen));
И тоже нифига(((

Ах да - устанавливаю размер буфера после успешного коннекта. До конекта не не ставится почему-то(
Ну соответственно и setsockopt отрабатывает на ноль)))


А вот блин какая ситуация интересная получается вне зависимости от входящих и исходящих буферов:
Если воткнуть перед командой send команду recv, которая пусть чегонить попробует прочесть и вот перед этой командой чтения выдернуть кабель из сетевухи, то получается что recv завершается c -1 и следующая за ней send так же завершается с -1.
Выходит команда recv обращается к какому-то механизму, который ей говорит о том, что тут дело шляпа и ждать уже ничего не нужно, так как нету связи((( Отваливается recv неспешно, через секунды четыре падла такая!

Очень уж не хотелось бы докапываться до правды прибегая к дизасемблеру((( Ну не должно быть так все скрытно(((
для FireSwarm:
Однако, протестировав аналогичную ситуацию переведя сокет в неблокирующий режим, recv отваливается сразу с -1, а вот send по прежнему возвращает количество байт, которое я прошу передать(((

Твою дивизию ... решив проверить еще одну ситуацию ... убрал команду чтения... и просто после разрыва соединения дал эти секунды четыре паузы и о боже мой.... команда сенд возвращает -1.


И что же мы имеем в итоге???
При реальном разрыве соединения, реакция происходит только через несколько секунд.

Ерунда какая-то получается в любом случае(((

Получается специальным образом, деструктивно создавая разрыв соединения именно в тот момент, когда проверено и якобы разрыва нет(ну пускай твоим селектом), но до момента отправки, можно повесить любое приложение написанное с применением инструментов предоставляемых программистам таких как winsock и аналогичные ему, которые не дают возможность проверять доведение(квитанции)(((

Чеж делать-та??? Как быть ?)))
для ChinaNoDollar:
А если пинг до адресата секунда или поболее и отпарвляться будет по одному пакету?
Это комментарий точно к первому решению был? Кажется, мы друг друга не поняли...

Твою дивизию ... решив проверить еще одну ситуацию ... убрал команду чтения... и просто после разрыва соединения дал эти секунды четыре паузы и о боже мой.... команда сенд возвращает -1.
Аллилуйа! Ты наконец сделал то, что было в решении 1))
А чем тебя удивляют 4 секунды? Логично, что задержка будет с погрешностью на пинги и т.д. TCP после отправки пакета выжидает время, если подтверждение не получено - отправляет ещё раз и снова ждёт. Само собой какая-то задержка перед окончательным решением о недоставленном пакете будет.

Решение 2
Ну а этот совет некудышный опять же по определению:
Ну и чего с того, что ты проверил соединение перед отправкой???

После отправки религия не позволяет проверить? Если соединение не разорвано, пакт дойдёт.
А те, кому супер-пупер достоверность доставк пакета нужна, пишут потокол поверх TCP с одтверждением и работают с ним. А то, что делаешь ты, по определению отвёрткой гвозди забивать. И при этом не корявое решение ищешь.
Развивая тему ламерищества твоих попыток.
Есть куча проблем, для решения которых нужно ваще гарантированная доставка пакетов. Рассмотрим один из них - загрузка файлов по HTTP с возможностью докачки. Так вот, для того, чтобы возможность докачки действительно была, её должны поддерживать и клиент, и сервер, и никто на уровень TCP и его гарантированность не полагается.
Для выполнения этой задачи, большой файл сперва сегментируется, потом отправляется кусками. Если связь оборвалась, после её восстановления клиент сообщает серверу последний полученный сегмент и сервер отправляет ему следующий. И чхали все на надёжности протоколов более низкого уровня.
для FireSwarm:
Это комментарий точно к первому решению был? Кажется, мы друг друга не поняли...

Ну я отвечая тебе оперся на теорию описанную выше:

...
Следующая задача протокола – обеспечить гарантированную доставку. Делается это с помощью следующей процедуры. Отправитель посылает пакет с номером n и начинает ждать. Получатель в случае успешного прихода пакета n, отправляет подтверждение о получении ("квитанцию"), в котором также указывает номер n. Если отправитель в течение определеннного времени (тайм-аута) не получает подтверждения, он считает пакет n потерянным и отсылает его еще раз.

Разумеется, отправителю неэффективно просто ждать, пока получатель получит и обработает каждый пакет по одному. Поэтому процедура усложняется, вводится специальное понятие – "окно" (window). Окно имеет некоторый размер, предположим, 10. Это означает, что передача начинается с отсылки 10 первых пакетов. Получатель может принять их не в том порядке, в каком они были отосланы. Тем не менее, на каждый успешно полученный пакет отсылается подтверждение с указанием номера такого пакета. Если отправитель отослал уже все 10 пакетов, но квитанция о получении пакета 1 так и не пришла, то передача приостанавливается, а по прошествии тайм-аута первый пакет считается потерянным и пересылается еще раз. Если же подтверждения приходят регулярно, то отправляются новые пакеты, но не более 10 единовременно.
...


И посчитал, что ты мне предложил как раз и установить это окно в ноль благодаря буферу отправки установленному в 0. Но в одной книжке вот читаю следующее примечание - "К сожалению, в реализациях WinSock SO_SNDBUF и SO_RCVBUF не имеют прямого отношения к размеру скользящего окна TCP [MSDN]".

Ну вот а собственно про долгие задержки я и написал исходя из того, что если размер этого окна зарубить, то получается что пока не прийдет подтверждение пакета, следующий не полетит, так как для того, чтобы пакеты летели один за одним(потоком) и выставляется как я понял это самое окно, которое в следующей партии если что дошлет не дошедшие пакеты.
для ChinaNoDollar:
ты мне предложил как раз и установить это окно в ноль благодаря буферу отправки установленному в 0.
Окно и буфер путать не нужно. Буфер предполагает, что когда ты данные отправляешь по сети, на самом деле они пишутся в буфер, а когда отправляются реально - одному шедулеру известно. По заполнению буфера, может и раньше, ХЗ. Поэтому, когда ты отправляешь пакет и сразу проверяешь ошибку - нет никакой гарантии, что реально была попытка отправить пакет, а соответственно, и переменная с ошибкой ещё не содержит нужной информации. Если же размер буфера будет 0, сразу будет его переполнение, а соответственно, гарантированно будет отправка, когда ты этого ожидаешь. Ну и есть смысл уже проверять, что там с ошибкой.
К размеру окна это никакого отношения не имеет.
К списку тем
2007-2025, онлайн игры HeroesWM