обсуждался вопрос, используют ли функции WSASend/WSARecv входные параметры _после_ прихода завершения на GetQueuedCompletionStatus, но _до_ выхода из этих функций.
Я, с некоторыми другими товарищами, активно настаивал что нет, не используют. Подразумевая, конечно, структуру OVERLAPPED, как основной объект.. хм.. динамизма И это так, её не используют.
Но есть другая проблема — структура WSABUF. Её таки держат:
If this function is completed in an overlapped manner, it is the Winsock service provider's responsibility to capture the WSABUF structures before returning from this call. This enables applications to build stack-based WSABUF arrays pointed to by the lpBuffers parameter. http://msdn.microsoft.com/en-us/library/ms742203(VS.85).aspx
Т.е. эти структуры надо создавать на стеке. Я всегда делал только так, и поэтому с проблемами нарушения доступа не сталкивался.
А вот кое-кто пихает куда не следует
Здравствуйте, Gomes, Вы писали:
G>Но есть другая проблема — структура WSABUF. Её таки держат: G>Т.е. эти структуры надо создавать на стеке. Я всегда делал только так, и поэтому с проблемами нарушения доступа не сталкивался. G>А вот кое-кто пихает куда не следует
хм, мне почему-то в приведенном абзаце из MSDN больше бросилось в глаза второе предложение:
If this function is completed in an overlapped manner, it is the Winsock service provider's responsibility to capture the WSABUF structures before returning from this call. This enables applications to build stack-based WSABUF arrays pointed to by the lpBuffers parameter. http://msdn.microsoft.com/en-us/library/ms742203(VS.85).aspx
то есть, приложения могут, а не обязаны создавать структуры на стеке.
G>обсуждался вопрос, используют ли функции WSASend/WSARecv входные параметры _после_ прихода завершения на GetQueuedCompletionStatus, но _до_ выхода из этих функций. G>Я, с некоторыми другими товарищами, активно настаивал что нет, не используют. Подразумевая, конечно, структуру OVERLAPPED, как основной объект.. хм.. динамизма И это так, её не используют.
* Asio:
...
o Fixed a problem with the lifetime of handler memory, where Windows needs the OVERLAPPED structure to be valid until both the initiating function call has returned and the completion packet has been delivered.
...
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Вообще интересно, что разработчики boost::asio имели в виду под приведенной в указанной теме фразой (http://www.boost.org/users/news/version_1_42_0): MC>Речь идет именно про OVERLAPPED, а не про WSABUF.
Качну, попробую разобраться. Хотя думаю там дебри ещё те
Здравствуйте, Pepel, Вы писали:
P>я WSABUF размещаю в куче и тащу адрес через поле OVERLAPPED на завершение — где и освобождаю/переразмещаю , за 9 месяце ни одного слета
G>>> // Check if the operation completed immediately.
G>>> if (result != 0 && last_error != WSA_IO_PENDING)
G>>>
MC>>Все правильно, в первом случае уведомления не поступит, во втором поступит.
G>Так, не понял. Это ж просто обработка ошибки, причем тут "operation completed immediately"?
Притом что уведомления не будет, операция сразу завершилась с ошибкой.
Здравствуйте, Gomes, Вы писали:
MC>>Притом что уведомления не будет, операция сразу завершилась с ошибкой.
G>Так ведь это ошибка, это не "operation completed immediately". Данные не ушли.
Ушли ли данные — это вопрос другой. Операция закончилась, ничего уже с ней связанного не будет.
Здравствуйте, Pepel, Вы писали:
P>я WSABUF размещаю в куче и тащу адрес через поле OVERLAPPED на завершение — где и освобождаю/переразмещаю , за 9 месяце ни одного слета
Ваши 9 месяцев не отменяют утверждения в MSDN по поводу необходимости держать WSABUF до выхода из WSASend (именно до выхода из WSASend, а не до завершения операции).
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Ушли ли данные — это вопрос другой. Операция закончилась, ничего уже с ней связанного не будет.
Мы как на разных языках щаз ;)
Это:
if (result != 0 && last_error != WSA_IO_PENDING)
проверка на ОШИБКУ!
Никаким "operation completed immediately" здесь не пахнет!
При "completed immediately":
1. result == 0;
2. как мы знаем завершенка приходит, и ничего дополнительно проверять не надо.
Здравствуйте, Gomes, Вы писали:
G>Это: G>if (result != 0 && last_error != WSA_IO_PENDING) G>проверка на ОШИБКУ! G>Никаким "operation completed immediately" здесь не пахнет!
А что, разве операция не завершилась? Причем ведь сразу, immediately
Тот факт, что произошла ошибка, никак не отменяет факт немедленного завершения операции.
G>При "completed immediately": G>1. result == 0;
Это частный случай. Completed immediately and successfully
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Тот факт, что произошла ошибка, никак не отменяет факт немедленного завершения операции. MC>Это частный случай. Completed immediately and successfully :)
Ты, видимо, в контексте темы пишешь. А я вообще. Криво же написано.
Здравствуйте, Gomes, Вы писали:
G>Или это такое глобальное обобщение — нет pending-а, значит immediately? G>Т.е. предлагают ошибку обрабатывать в рабочем потоке.
А где ее еще обрабатывать, если уведомления не будет?
Все правильно у них написано.
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Здравствуйте, Pepel, Вы писали:
P>>я WSABUF размещаю в куче и тащу адрес через поле OVERLAPPED на завершение — где и освобождаю/переразмещаю , за 9 месяце ни одного слета
MC>Ваши 9 месяцев не отменяют утверждения в MSDN по поводу необходимости держать WSABUF до выхода из WSASend (именно до выхода из WSASend, а не до завершения операции).
ок, спасибо, вот прочитал этот абзац — ведь мы на вход WSASend подаем в общем случае массив структур WSABUF (пара длина / адрес данных), меня (возможно !) спасает от слета тот факт, что этот массив у меня сознательно одноэлементный , а если у кого-то в нем сотни буферов на передачу, то тут высоковероятна шляпа — за одно завершение этот массив не отправится и значит не следует его валить на первом же завершении , т.е. предупреждение авторов документации оно для всех и на все случаи, так что ли
Здравствуйте, Gomes, Вы писали:
MC>>Возвратом куда? G>В вызывающую функцию, куда ж ещё.
Будет еще один if, теперь уже в вызывающй функции. Толку-то?
А так — обычный обработчик немедленного выполнения операции.
Не забывай, что boost::asio не ограничивается Windows. Если WSASend отправляет уведомление всегда, даже в случае немедленного выполнения, то для методов на других системах (kqueue, epoll, ...) это [может быть] не так.
MC>>И как это должно сменить поток? G>Зачем?
Ты возмущался, что они-де "предлагают ошибку обрабатывать в рабочем потоке".
Здравствуйте, Pepel, Вы писали:
P>а если у кого-то в нем сотни буферов на передачу, то тут высоковероятна шляпа — за одно завершение этот массив не отправится и значит не следует его валить на первом же завершении
Уведомление о завершении операции одно и только одно на операцию, вне зависимости от количества структур WSABUF.
А спасает тебя скорее всего конкретная реализация [на конкретной версии Windows], которая на самом деле не трогает WSABUF после начала операции. Но нет гарантии, что эта реализация не меняется (или не будет меняться) от версии к версии.
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Уведомление о завершении операции одно и только одно на операцию, вне зависимости от количества структур WSABUF.
э-э-э-э, стоп, прямой зависимости нет , но так понимаю чем больше данных ставим на передачу (вот тот же массив WSABUF погуще), тем все таки вероятней, что сетевая подсистема будет отсылать их частями и уведомлений о завершении операции будет более одного
Здравствуйте, Pepel, Вы писали:
MC>>Уведомление о завершении операции одно и только одно на операцию, вне зависимости от количества структур WSABUF.
P>э-э-э-э, стоп, прямой зависимости нет , но так понимаю чем больше данных ставим на передачу (вот тот же массив WSABUF погуще), тем все таки вероятней, что сетевая подсистема будет отсылать их частями и уведомлений о завершении операции будет более одного
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Будет еще один if, теперь уже в вызывающй функции. Толку-то? MC>А так — обычный обработчик немедленного выполнения операции.
Я к тому, что сложная функция должна вернуть код ошибки, а не выдавать его через хитрый механизм.
А если после Send() надо выполнить код, зависящий от этого?
MC>Ты возмущался, что они-де "предлагают ошибку обрабатывать в рабочем потоке".
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Здравствуйте, Pepel, Вы писали:
MC>>>Уведомление о завершении операции одно и только одно на операцию, вне зависимости от количества структур WSABUF.
P>>э-э-э-э, стоп, прямой зависимости нет , но так понимаю чем больше данных ставим на передачу (вот тот же массив WSABUF погуще), тем все таки вероятней, что сетевая подсистема будет отсылать их частями и уведомлений о завершении операции будет более одного
MC>Еще раз. ОДНО И ТОЛЬКО ОДНО.
вот это подозреваю действительно платформозависимое утверждение
Здравствуйте, Pepel, Вы писали:
P>>>э-э-э-э, стоп, прямой зависимости нет , но так понимаю чем больше данных ставим на передачу (вот тот же массив WSABUF погуще), тем все таки вероятней, что сетевая подсистема будет отсылать их частями и уведомлений о завершении операции будет более одного
MC>>Еще раз. ОДНО И ТОЛЬКО ОДНО.
P>вот это подозреваю действительно платформозависимое утверждение
Отнюдь. На этом, собственно, все и работает. Один вызов ввода-вывода — одно и только одно уведомление.
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Отнюдь. На этом, собственно, все и работает. Один вызов ввода-вывода — одно и только одно уведомление.
кабы так зачем тогда GetQueuedCompletionStatus() второй параметр :
lpNumberOfBytes
[out] Pointer to a variable that receives the number of bytes transferred during an I/O operation that has completed.
если всегда одно срабатывание на один инициатор отсылки/приема ?
можно было бы думать, что на случай когда частичная отсылка — результат отказа на транспорте и нам надо знать что таки ушло (зачем ??) , но таки это нигде не сказано, вот уже где действительно лучше перестраховаться если нет прямых указаний вести себя так или иначе
Здравствуйте, Pepel, Вы писали:
MC>>Отнюдь. На этом, собственно, все и работает. Один вызов ввода-вывода — одно и только одно уведомление.
P>кабы так зачем тогда GetQueuedCompletionStatus() второй параметр :
P>lpNumberOfBytes P>[out] Pointer to a variable that receives the number of bytes transferred during an I/O operation that has completed.
P>если всегда одно срабатывание на один инициатор отсылки/приема ? P>можно было бы думать, что на случай когда частичная отсылка — результат отказа на транспорте и нам надо знать что таки ушло (зачем ??) ,
Именно для этого. Только больше не для write/send, а для read/recv. Там необходимость этого параметра, надеюсь, очевидна.
P>но таки это нигде не сказано,
Про возможность чтения/записи меньшего количества байт, нежели запрошено, сказано в описании любой функции ввода-вывода.
P>вот уже где действительно лучше перестраховаться если нет прямых указаний вести себя так или иначе
Когда Вы взлетаете на самолете, тоже рассчитываете сесть несколько раз, если лететь далеко?
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Здравствуйте, Pepel, Вы писали:
MC>>>Отнюдь. На этом, собственно, все и работает. Один вызов ввода-вывода — одно и только одно уведомление.
P>>кабы так зачем тогда GetQueuedCompletionStatus() второй параметр :
P>>lpNumberOfBytes P>>[out] Pointer to a variable that receives the number of bytes transferred during an I/O operation that has completed.
P>>если всегда одно срабатывание на один инициатор отсылки/приема ? P>>можно было бы думать, что на случай когда частичная отсылка — результат отказа на транспорте и нам надо знать что таки ушло (зачем ??) ,
MC>Именно для этого. Только больше не для write/send, а для read/recv. Там необходимость этого параметра, надеюсь, очевидна.
P>>но таки это нигде не сказано,
MC>Про возможность чтения/записи меньшего количества байт, нежели запрошено, сказано в описании любой функции ввода-вывода.
P>>вот уже где действительно лучше перестраховаться если нет прямых указаний вести себя так или иначе
MC>Когда Вы взлетаете на самолете, тоже рассчитываете сесть несколько раз, если лететь далеко?
ок, спасибо!!, Михаил я все-таки не поленюсь и вкатаю строчку логирования для ситуации порциональной отсылки посредством WSASend в несолько срабатываний GetQueuedCompletionStatus(), модуль (смс-рассылка) плотно работает круглосуточно и мож когда порадует а я тогда вас порадую