Если я правильно понимаю, то, обычно, перед очередным WSASend на IOCP можно не ждать завершения предыдущего WSASend.
В таком случаи система перекладывает данные к себе, меня по-быстрому отпускает, а сама потихоньку отправляет данные.
Если данных будет слишком — я получу WSAENOBUFS — после чего нормально работать с сокетом уже невозможно (у меня не получилось).
Решение с WSAGetOverlappedResult когда (fWait = false) уж очень некрасивое, а когда (fWait = true) – может усыпить поток навсегда.
Как правильно (не создавая Event-ов или прочей синхры) разрешить эту ситуацию (подождать завершения предыдущего WSASend) ?
Здравствуйте, v2, Вы писали:
v2>Если я правильно понимаю, то, обычно, перед очередным WSASend на IOCP можно не ждать завершения предыдущего WSASend. v2> В таком случаи система перекладывает данные к себе, меня по-быстрому отпускает, а сама потихоньку отправляет данные.
А насколько я понимаю она не перекладывает себе данные. если ты их разрушишь до того как она пошлет, то будет ошибка.
У тебя уже есть IOCP. Тогда делается так, в WSAsend передается не overlapped а твоя структура большего размера в котором только начало overlapped.
Когда wsasend произойдет, ты получишь указатель на свою структуру (он же на overlapped). Исходя из нее, поймешь какие буфера посланы и что можно освобождать.
Очень удобно в одном потоке создаешь буферы и в сенд, в другом получаешь completition и освобождаешь (или складываешь в пустые)
Re[2]: Как правильно предупредить WSAENOBUFS при WSASend на IOCP TCP
Здравствуйте, Kubyshev Andrey, Вы писали: KA>А насколько я понимаю она не перекладывает себе данные. если ты их разрушишь до того как она пошлет, то будет ошибка.
Как только WSASend завершилась с WSA_IO_PENDING делаю с данными что хочу — проблем не наблюдал (ну что ж, потестирую еще и в этом ключе),
а вот размер невыгружаемой памяти ядра временно увеличивается, что можно объяснить как дублирование (кэширование) моих данных системой
KA>У тебя уже есть IOCP. Тогда делается так, в WSAsend передается не overlapped а твоя структура большего размера в котором только начало overlapped.
Да, так и есть.
KA>Когда wsasend произойдет, ты получишь указатель на свою структуру (он же на overlapped). Исходя из нее, поймешь какие буфера посланы и что можно освобождать. KA>Очень удобно в одном потоке создаешь буферы и в сенд, в другом получаешь completition и освобождаешь (или складываешь в пустые)
Как раз это таки и не удобно, — зачем накладывать дополнительные ограничения на 'пользователя' или же 'самому' дублировать данные.
Вот м$ные ребята и сказали: нате асинхронную отсылку, а мы там сами уже, нам виднее как. (Ну, это я так думаю, — вроде логично.)
Вопрос открыт, буду рад почитать Ваши мысли.
Re[3]: Как правильно предупредить WSAENOBUFS при WSASend на IOCP TCP
KA>>А насколько я понимаю она не перекладывает себе данные. если ты их разрушишь до того как она пошлет, то будет ошибка. v2>Как только WSASend завершилась с WSA_IO_PENDING делаю с данными что хочу — проблем не наблюдал (ну что ж, потестирую еще и в этом ключе), v2>а вот размер невыгружаемой памяти ядра временно увеличивается, что можно объяснить как дублирование (кэширование) моих данных системой
Инфа соточка! Ф-ция сохранаяет только WSABUF структуру, но НЕ ДАННЫЕ в буфферах, и так вощем то и с обычным overlapped WriteFile.
Re: Как правильно предупредить WSAENOBUFS при WSASend на IOCP TCP
Здравствуйте, v2, Вы писали:
v2>Если я правильно понимаю, то, обычно, перед очередным WSASend на IOCP можно не ждать завершения предыдущего WSASend.
Вроде ж написано: "the system owns these buffers and the application may not access them. This array must remain valid for the duration of the send operation."
Re[2]: Как правильно предупредить WSAENOBUFS при WSASend на IOCP TCP
Здравствуйте, Gomes, Вы писали: v2>>Если я правильно понимаю, то, обычно, перед очередным WSASend на IOCP можно не ждать завершения предыдущего WSASend. G>Вроде ж написано: "the system owns these buffers and the application may not access them. This array must remain valid for the duration of the send operation."
Если Вам не сложно, напишите, пожалуйста, перевод этой фразы, и как Вы его/её понимаете.
А по вопросу, как в отсылающем потоке подождать завершения отсылки предыдущих данных, что-то скажите?
Re[4]: Как правильно предупредить WSAENOBUFS при WSASend на IOCP TCP
Здравствуйте, Kubyshev Andrey, Вы писали: KA>Инфа соточка! Ф-ция сохранаяет только WSABUF структуру, но НЕ ДАННЫЕ в буфферах, и так вощем то и с обычным overlapped WriteFile.
Может есть какая настройка, которой обусловлено такое поведение,
потому что моё беглое тестирование маленько, но таки отгрызло чуток у Вашей соточки
Експресс-тест: (WiFi ~11Mb — типа медленно)
{
. Отправитель: (W7 64)
. Процедура-тест из GUI потока, один и тот же буфер 32К (на стеке),
. иная монозаливка перед каждым (х200) WSASend, WSASend не дожидаясь окончания предыдущего
. да, к тому же, со старой(тот же указатель) незачищенной Overlapped.
. Получатель: (W7 32)
. Что получает, то и показывает.
. Запуск:
. Кнопочка "тест" отскакивает на GUI почти сразу (можно подряд даже несколько раз нажать — так и делал).
. Диспетчер задач показывает увеличение невыгружаемой памяти ядра и передачу по WiFi.
. Передача идет несколько секунд, невыгружаемая память ядра возвращается в 'норму'.
. Результат: (неоднократный)
. Получатель показывает разные монозалитые блоки данных
. ( а ожидалось то, что с какого-то момента тотальный монолит — последняя монозаливка последнего сенда).
}
Как-то прокомментируете?
)
Re[5]: Как правильно предупредить WSAENOBUFS при WSASend на IOCP TCP
Здравствуйте, v2, Вы писали:
v2>Если Вам не сложно, напишите, пожалуйста, перевод этой фразы, и как Вы его/её понимаете.
Разве могут быть неопределённые толкования? Говорят, не трогайте буфера до окончания передачи.
Вот тут
было похожее обсуждение.
v2>А по вопросу, как в отсылающем потоке подождать завершения отсылки предыдущих данных, что-то скажите?
По GetQueuedCompletionStatus конечно.
Re[4]: Как правильно предупредить WSAENOBUFS при WSASend на IOCP TCP
Здравствуйте, Gomes, Вы писали:
v2>>Если Вам не сложно, напишите, пожалуйста, перевод этой фразы, и как Вы его/её понимаете. G>Разве могут быть неопределённые толкования? Говорят, не трогайте буфера до окончания передачи.
Ну, не силен я в переводах. А вот "веконулевой" говорит так:
lpBuffers [in]
A pointer to an array of WSABUF structures. Each WSABUF structure contains a pointer to a buffer and the length of the buffer, in bytes. For a Winsock application, once the WSPSend function is called, the system owns these buffers and the application may not access them. This array must remain valid for the duration of the send operation.
lpBuffers [in]
Указатель на массив WSABUF структур. Каждый WSABUF структура содержит указатель на буфер и размер буфера в байтах. Для приложения Winsock, как только WSPSend функция вызывается, система владеет этими буферами // ( как бы это на понятный программисту перевести ? ) и приложение не может получить к ним доступ. // ( это что ж, я уже и к своему стеку не подступлюсь ? ) Этот массив // ( думаю это о массив WSABUF структур ) должен оставаться в силе в течение всего срока операции отправки. // ( ага, а там дальше и для самого интересного — overlapped manner )
The array of WSABUF structures pointed to by the lpBuffers parameter is transient. If this operation completes in an overlapped manner, it is the service provider's responsibility to capture these WSABUF structures before returning from this call. This enables applications to build stack-based WSABUF arrays
...
Who Manages the Buffers?
As just mentioned, AFD.SYS handles buffer management for applications that use Winsock to talk to the transport protocol drivers. This means that when an application calls the send or WSASend function to send data, the data gets copied by AFD.SYS to its internal buffers (up to the SO_SNDBUF setting) and the send or WSASend function returns immediately. The data is then sent by AFD.SYS behind the application's back, so to speak. Of course, if the application wants to issue a send for a buffer larger than the SO_SNDBUF setting, the WSASend call blocks until all the data is sent.
...
v2>>А по вопросу, как в отсылающем потоке подождать завершения отсылки предыдущих данных, что-то скажите? G>По GetQueuedCompletionStatus конечно.
Извините, переуточню вопрос:
Как в отсылающем потоке (не обязательно это будет один из тех который висит на GetQueuedCompletionStatus, — например GUI)
подождать завершения отсылки предыдущих данных?
( Это на случай если одним сендом не отделаешься, и сразу же нужен второй, третий ... ... а там раз — и WSAENOBUFS! Вот в чем вопрос. )
Re[5]: Как правильно предупредить WSAENOBUFS при WSASend на IOCP TCP
Здравствуйте, v2, Вы писали:
v2>Ну, не силен я в переводах. А вот "веконулевой" говорит так:
Разве из всего этого непонятно, что трогать не надо? ;)
v2>однозначно там ребята с этим вопросом так и не определились
Однозначно не определились с тем, что делает система с буферами. Но это не наше дело. Ну, то есть ради академического интересу можно копать конечно.
v2>Who Manages the Buffers?
Ага, вспомнил такую статью.
v2>Как в отсылающем потоке (не обязательно это будет один из тех который висит на GetQueuedCompletionStatus, — например GUI) подождать завершения отсылки предыдущих данных?
Это кривая архитектура. Даже голову ломать не хочется, как это можно организовать ;)
Re[6]: Как правильно предупредить WSAENOBUFS при WSASend на IOCP TCP
Здравствуйте, Gomes, Вы писали:
v2>>Как в отсылающем потоке (не обязательно это будет один из тех который висит на GetQueuedCompletionStatus, — например GUI) подождать завершения отсылки предыдущих данных? G>Это кривая архитектура. Даже голову ломать не хочется, как это можно организовать
Хорошо, возможно что и кривая, а как у Вас (в двух словах) организована отправка данных.
( 'кто' и где может ее инициировать, как и где и когда узнает о завершении )
Спасибо.
Re[7]: Как правильно предупредить WSAENOBUFS при WSASend на IOCP TCP
Здравствуйте, v2, Вы писали:
v2>Хорошо, возможно что и кривая, а как у Вас (в двух словах) организована отправка данных. v2>( 'кто' и где может ее инициировать, как и где и когда узнает о завершении )
Слишком абстрактный вопрос. В общем случае — есть рабочий пул потоков. Подключается клиент, начинается работа по протоколу. Приём/передача/ожидание делается в этом пуле. В некоторых случаях отправка может осуществляться из других потоков, но ожидание завершения происходит в рабочем пуле, и обрабатывается там по протоколу. В качестве примера последней модели можешь глянуть в моей библиотеке prostoserver пример FileEcho.
Re[8]: Как правильно предупредить WSAENOBUFS при WSASend на IOCP TCP
Здравствуйте, Gomes, спасибо за разъяснение.
G>В общем случае — есть рабочий пул потоков. Подключается клиент, начинается работа по протоколу. Приём/передача/ожидание делается в этом пуле. В некоторых случаях отправка может осуществляться из других потоков, но ожидание завершения происходит в рабочем пуле, и обрабатывается там по протоколу. G>В качестве примера последней модели можешь глянуть в моей библиотеке prostoserver пример FileEcho.
Да, так и есть, это я что-то сошел с асинхронной тропы ( в выходные нужно было отдыхать ).