Здравствуйте, abrarov, Вы писали:
A>... лучше почитать "Programming Server-Side Applications for Microsoft Windows 2000" на тему размера пула потоков, обслуживающих IOCP, и выноса длительной работы в другой пул/потоки.
Здравствуйте, bolt7, Вы писали:
B> одному и томуже dest. как я должен теперь разрулить отправку через wsasend.
wsasend
завершение
wsasend
завершение
wsasend
завершение
...
B>по поводу отправки размера и самих даных если я правильно понял то это — выдиляем новый буфер size+2
Есть постоянный буфер на подключение — например, 8Кб. В первые 2 байта пишешь размер, потом добиваешь данными, отправляешь сколько надо.
B>и кстате почему 2 байта на размер, что нельзя послать за раз больше 64кб?
Да хоть 8 байт сделай, твой протокол. Понятно, большие данные шлёшь кусками, размером с буфер.
G>Читал. Проблемы не увидел, честно. Может проблема проявляется где-то, с чем-то я не сталкивался. Вот пишу я PortMapper (прокси), там на сокете одновременно передача и приём. Проблем нет.
Используем пул потоков (T1, T2), обслуживающих один IOCP и несколько сокетов (сервер, клиент с несколькими сокетами) — A, B, C, D.
Предположим, per-socket-data (в т.ч. сам сокет), Вы защищаете mutex-ом (по одному на каждый сокет).
Предположим, до окончания обработки рабочим потоком T1 одного completion packet, относящегося к сокету A, придет следующий completion packet, относящийся к тому же сокету A.
В этой ситуации из пула поднимается рабочий поток T2 и пытается обработать completion packet сокета A.
T2 застревает на mutex сокета A, так как T1 еще не закончил обработку.
В тоже время в IOCP имеется еще несколько готовых completion packets для сокетов B, C, D, которые могли бы быть обработаны потоком T2, пока T1 не закончил с сокетом A.
G>Теряюсь. Какая разница какой поток пишет/читает?
Дуплексный != thread-safe.
Programs must be written for people to read, and only incidentally for machines to execute
A>>... лучше почитать "Programming Server-Side Applications for Microsoft Windows 2000" на тему размера пула потоков, обслуживающих IOCP, и выноса длительной работы в другой пул/потоки.
G>Это топикстартеру?
Да. Здесь нельзя редактировать сообщения — приходится изощряться.
Programs must be written for people to read, and only incidentally for machines to execute
Здравствуйте, abrarov, Вы писали: A>"Выделять буферы" вообще лишнее — используем один буфер и serializator + очередь ref-counted сообщений.
как — то страшно звучит, 2 сенда не быстрее уже тогда сделать и надеятся что алгоритм нагла успеет сработать, и отправится как за один сенд
B>как — то страшно звучит, 2 сенда не быстрее уже тогда сделать и надеятся что алгоритм нагла успеет сработать, и отправится как за один сенд
Не нашел в MSDN (хотя где-то здесь писали, что по факту это так) упоминания о том, что асинхронная отправка завершается (приходит completion packet), только тогда, когда все данные, на которые указывает буфер, отправлены (а не когда отправлено хоть что-то из того, что было указано в WSASend). Подумайте, что будет, со вторым send, вызванным еще до завершения предыдущего. Зачем-то же GetQueuedCompletionStatus возвращает через lpNumberOfBytes кол-во отправленных/полученных байт.
Programs must be written for people to read, and only incidentally for machines to execute
Здравствуйте, abrarov, Вы писали:
G>>Читал. Проблемы не увидел, честно. Может проблема проявляется где-то, с чем-то я не сталкивался. Вот пишу я PortMapper (прокси), там на сокете одновременно передача и приём. Проблем нет.
A>Используем пул потоков (T1, T2), обслуживающих один IOCP и несколько сокетов (сервер, клиент с несколькими сокетами) — A, B, C, D. A>Предположим, per-socket-data (в т.ч. сам сокет), Вы защищаете mutex-ом (по одному на каждый сокет). A>Предположим, до окончания обработки рабочим потоком T1 одного completion packet, относящегося к сокету A, придет следующий completion packet, относящийся к тому же сокету A. A>В этой ситуации из пула поднимается рабочий поток T2 и пытается обработать completion packet сокета A. A>T2 застревает на mutex сокета A, так как T1 еще не закончил обработку. A>В тоже время в IOCP имеется еще несколько готовых completion packets для сокетов B, C, D, которые могли бы быть обработаны потоком T2, пока T1 не закончил с сокетом A.
Вы не правы, так делать не нужно — не нужно синхронизировать работу с сокетом mutex-ом — это все портит. Нужно использовать что-то вроде lock-free, а для того чтобы восстановить порядок буферов при вызове recv в структуре нужно указать номер операции. Но даже если делать через блокировки, то чтобы решить проблему которую вы описали в своем примере, необходимо просто сделать очередь необработанных запросов. Хотя это на мой взгляг не есть гуд, но это простое и очевидное решение, которое довольно часто используется.
G>>Теряюсь. Какая разница какой поток пишет/читает? A>Дуплексный != thread-safe.
Опять не правы... виндовые сокете потокобезопасны, тут есть другой подводный камень...
Здравствуйте, vf.
A>>Используем пул потоков (T1, T2), обслуживающих один IOCP и несколько сокетов (сервер, клиент с несколькими сокетами) — A, B, C, D. A>>Предположим, per-socket-data (в т.ч. сам сокет), Вы защищаете mutex-ом (по одному на каждый сокет). A>>Предположим, до окончания обработки рабочим потоком T1 одного completion packet, относящегося к сокету A, придет следующий completion packet, относящийся к тому же сокету A. A>>В этой ситуации из пула поднимается рабочий поток T2 и пытается обработать completion packet сокета A. A>>T2 застревает на mutex сокета A, так как T1 еще не закончил обработку. A>>В тоже время в IOCP имеется еще несколько готовых completion packets для сокетов B, C, D, которые могли бы быть обработаны потоком T2, пока T1 не закончил с сокетом A.
vf>Вы не правы, так делать не нужно — не нужно синхронизировать работу с сокетом mutex-ом — это все портит. Нужно использовать что-то вроде lock-free, а для того чтобы восстановить порядок буферов при вызове recv в структуре нужно указать номер операции. Но даже если делать через блокировки, то чтобы решить проблему которую вы описали в своем примере, необходимо просто сделать очередь необработанных запросов. Хотя это на мой взгляг не есть гуд, но это простое и очевидное решение, которое довольно часто используется.
Я как раз таки против использования мьютекса — мне нравится boost::asio::io_sevice::strand — а это и есть очередь
G>>>Теряюсь. Какая разница какой поток пишет/читает? A>>Дуплексный != thread-safe. vf>Опять не правы... виндовые сокете потокобезопасны, тут есть другой подводный камень...
Я не утверждаю, что виндовые сокеты непотокобезопасны. Я просто не нашел в MSDN явного указания на то, что они потокобезопасны — может кто даст ссылку?
А подводный камень есть в том, что (я уже писал в этом топике) в MSDN нет гарантий того, что асинхронная отправка (WSASend) успешно завершается лишь после отправки всего (а не хотя бы чего-то), что было предложено передать при вызове WSASend (может я ошибаюсь?).
К тому же с сокетом часто ассоциировано состояние сессии, поэтому, когда использется полноценная дуплексная логика (см. док-цию Boost.Asio — implicit strand & explicit strand), появляется необходимость синхронизировать доступ к этому состоянию.
Programs must be written for people to read, and only incidentally for machines to execute
Здравствуйте, abrarov, Вы писали:
G>>>>Теряюсь. Какая разница какой поток пишет/читает? A>>>Дуплексный != thread-safe. vf>>Опять не правы... виндовые сокете потокобезопасны, тут есть другой подводный камень...
A>Я не утверждаю, что виндовые сокеты непотокобезопасны. Я просто не нашел в MSDN явного указания на то, что они потокобезопасны — может кто даст ссылку?
Да, в мсдн-е не находится... наверное нужно искать в книжках у мс-вских гуру. http://tangentsoft.net/wskfaq/intermediate.html#threadsafety
Там же, к конце про то что я считаю подводным камнем.
A>А подводный камень есть в том, что (я уже писал в этом топике) в MSDN нет гарантий того, что асинхронная отправка (WSASend) успешно завершается лишь после отправки всего (а не хотя бы чего-то), что было предложено передать при вызове WSASend (может я ошибаюсь?).
Думаю, что ошибаетесь. Мне такое поведение видится абсолютно абсурдным, в контексте того что допускается многократный вызов WSASend до завершения операции, потому что не оставляет никаких возможностей продолжить передачу данных.
Здравствуйте, abrarov, Вы писали:
A>А подводный камень есть в том, что (я уже писал в этом топике) в MSDN нет гарантий того, что асинхронная отправка (WSASend) успешно завершается лишь после отправки всего (а не хотя бы чего-то), что было предложено передать при вызове WSASend (может я ошибаюсь?).
Уведомление о завершении приходит, когда "освобождаются" переданные в WSASend пользовательские буферы. То есть получив уведомление об успехе, Вы вольны делать с буферами что угодно, системе их содержимое более не требуется. Но это совершенно не означает, что все данные или хотя-бы их часть уже отправлены, при ненулевых буферах сокета(SO_SNDBUF) система просто копирует Ваши данные в свой внутренний буфер и сразу извещает Вас о завершении операции.
Здравствуйте, Jolly Roger.
JR>Уведомление о завершении приходит, когда "освобождаются" переданные в WSASend пользовательские буферы. То есть получив уведомление об успехе, Вы вольны делать с буферами что угодно, системе их содержимое более не требуется. Но это совершенно не означает, что все данные или хотя-бы их часть уже отправлены, при ненулевых буферах сокета(SO_SNDBUF) система просто копирует Ваши данные в свой внутренний буфер и сразу извещает Вас о завершении операции.
... If the overlapped operation is successfully initiated and will complete later, WSASend returns SOCKET_ERROR and indicates error code WSA_IO_PENDING. In this case, lpNumberOfBytesSent is not updated. When the overlapped operation completes the amount of data transferred is indicated either through the cbTransferred parameter in the completion routine (if specified), or through the lpcbTransfer parameter in WSAGetOverlappedResult.
но
If you are using I/O completion ports, be aware that the order of calls made to WSASend is also the order in which the buffers are populated. WSASend should not be called on the same socket simultaneously from different threads, because it can result in an unpredictable buffer order.
Написать прямым текстом о том, что обсуждается в этой ветке, видимо, не позволяет религия.
Опять же, могли бы предупредить, что completion packet м/б выбран рабочим потоком из IOCP еще до выхода из WSASend/WSARecv...
Programs must be written for people to read, and only incidentally for machines to execute
а если одновременно по одному и тому же соединению с разных концов (и клиент и сервер) пишет чтото, данные не перемешаются и каждый из сторон получат то что им отправляли? или нет?
Здравствуйте, Аноним, Вы писали:
А>а если одновременно по одному и тому же соединению с разных концов (и клиент и сервер) пишет чтото, данные не перемешаются и каждый из сторон получат то что им отправляли? или нет?
Соединение полнодуплексное. Значит юзается два буфера (для каждого направления передачи).
Re: wsasend синхронизация
От:
Аноним
Дата:
07.04.12 10:19
Оценка:
здравствуйте, проясните пожалуйсто ситуацию с передачей больших данных (в несколько мегабайт). мне нужно их самому отправлять порциями или ядро само это сделает, и если да то какой размер порции должен быть чтоб маршрутизатор пропустил?