подскажите пожалуйста, если а асинхронном режиме (или в синхронном но 2 потока) пишут данные в один и тот же сокет, будет ли по порядку отправлено или же смешается в одну кучу, другими есть ли синхронизация на уровни ядра?
Re: wsasend синхронизация
От:
Аноним
Дата:
03.04.12 14:33
Оценка:
Здравствуйте, bolt7, Вы писали:
B>подскажите пожалуйста, если а асинхронном режиме (или в синхронном но 2 потока) пишут данные в один и тот же сокет, будет ли по порядку отправлено или же смешается в одну кучу, другими есть ли синхронизация на уровни ядра?
Блоки будут перемешаны естественно. Возникает вопрос — зачем два потока? Не могу придумать, зачем это могло бы понадобится?
я делаю одну библиотеку для обмена сообщениями и юзер может свободно два раза подряд отправить одному и тому же получателю разные сообщения. делаю на iocp. неужели придется синхронизировать евентами? использовать блокирующие сокеты не хочу, так как если отправляется двум разным получателям будет дольше.
Здравствуйте, bolt7.
B>я делаю одну библиотеку для обмена сообщениями и юзер может свободно два раза подряд отправить одному и тому же получателю разные сообщения. делаю на iocp. неужели придется синхронизировать евентами? использовать блокирующие сокеты не хочу, так как если отправляется двум разным получателям будет дольше.
Когда-то тоже начинал писать на raw IOCP. И тоже столкнулся с подобным вопросом (у меня были одновременная отправка и получение). Потом перешел на Boost.Asio. Там проблема решена так. Мне это решение очень понравилось и, наряду с таймерами, повернуло мой проект в сторону Asio.
Programs must be written for people to read, and only incidentally for machines to execute
а разве для приема и отправки не два разных буфера? у меня проект на си, так что никаких классов. да и тем более у меня должна выйти легкая и быстрая библиотечка, и использовать библиотеки классов рассчитаны на все случаи жизни, тут будет неоправданная роскошь. будем думать...
B>а разве для приема и отправки не два разных буфера?
Проблема не в буферах, а в общих для обеих операций (и не только для них — есть еще таймеры и внешнее управление) per-socket-data. В основном, это флаги состояний сессии: идет ли операция чтения, идет ли операция записи, получен ли сигнал к завершению работы или прочие сигналы внешнего управления. Не вводить же mutex на каждую сессию — он может заблокировать более одного рабочего потока из пула, обслуживающего IOCP, в случае, когда до окончания обработки одного completion packet придет следующий completion packet, относящийся к тому же сокету. В подобной ситуации работать будет только один рабочий поток — остальные будут просто ждать в то время, как на обслуживаемом ими IOCP могут быть другие готовые completion packet, относящиеся к другим сокетам и, следовательно, позволяющие обработать их параллельно.
И еще — я не нашел в MSDN информации, подтверждающей допустимость одновременного использования одного и того же сокета из разных потоков. Может кто подскажет?
Programs must be written for people to read, and only incidentally for machines to execute
Здравствуйте, bolt7, Вы писали:
B>а как быть если не знаешь заранее размер посланных данных? посылать сначала длину, а потом сами данные; или как то по изящнее можно?
Как это не знаешь размер посланных? Так да, стандартно, придумываешь протокол — 2 (4) байта длина, потом данные. Часто делается заголовок — длина, команда, опции и потом данные (или без данных).
Здравствуйте, abrarov, Вы писали:
A>Проблема не в буферах, а в общих для обеих операций (и не только для них — есть еще таймеры и внешнее управление) per-socket-data.
Не вижу проблемы. Может, неудачное проектирование?
A>И еще — я не нашел в MSDN информации, подтверждающей допустимость одновременного использования одного и того же сокета из разных потоков. Может кто подскажет?
А почему нет то? Сокет дуплексный, к потокам не привязан.
в смысле мне посланных)и это придется в два захода считывать — размер, потом выделить буфера и сами данные. меня только волнует если опять таки одновременно будут слать по одному сокету несколько потоков на принимающей стороне я не разберусь что к чему. нормально будет сделать на каждое соединению по одному евенту/мутексу и пока один не закончит передачу, второй ждет на этом объекте? не будет ли перевод в спячку и обратно слишком затратной операцией? (будет дольше проворачивать все это дело, чем слать данные)
Здравствуйте, bolt7, Вы писали:
B>в смысле мне посланных)и это придется в два захода считывать — размер, потом выделить буфера и сами данные.
Ну ты что, 2 байта считывать будешь? Читаешь то в размер буфера. Принял всё, и потом разбираешь.
B>меня только волнует если опять таки одновременно будут слать по одному сокету несколько потоков на принимающей стороне я не разберусь что к чему.
Кто тебе будет слать? Давай сферическое не обсуждать. Придумал конкретную схему обмена, конкретный протокол, и реализовываешь.
B>нормально будет сделать на каждое соединению по одному евенту/мутексу и пока один не закончит передачу, второй ждет на этом объекте?
Послали, получили уведомление о завершении, послали ещё порцию. Не надо мудрить.
B>в смысле мне посланных)и это придется в два захода считывать — размер, потом выделить буфера и сами данные.
Читать можно и больше, чем только заголовок — по завершении операции чтения парсим все, что прочиталось. Где-то я уже видел обсуждение этого. Кажется, на vingrad-е.
B>меня только волнует если опять таки одновременно будут слать по одному сокету несколько потоков на принимающей стороне я не разберусь что к чему.
Если речь идет о TCP, то это потоковый протокол и разделение сообщений должно быть реализовано приложением. Накапавливаем исходящие сообщения в собственном буфере (в очереди) и отсылаем их по мере возможности (после успешного завершения очередной операции отправки).
B>нормально будет сделать на каждое соединению по одному евенту/мутексу и пока один не закончит передачу, второй ждет на этом объекте? не будет ли перевод в спячку и обратно слишком затратной операцией? (будет дольше проворачивать все это дело, чем слать данные)
A>>Проблема не в буферах, а в общих для обеих операций (и не только для них — есть еще таймеры и внешнее управление) per-socket-data.
G>Не вижу проблемы. Может, неудачное проектирование?
читали остальную часть моего сообщения или хотя бы Network Programming for Microsoft Windows?
A>>И еще — я не нашел в MSDN информации, подтверждающей допустимость одновременного использования одного и того же сокета из разных потоков. Может кто подскажет?
G>А почему нет то? Сокет дуплексный, к потокам не привязан.
То, что сокет дуплексный, не подразумевает, что один и тот же сокет можно безопасно использовать одновременно из нескольких потоков.
Programs must be written for people to read, and only incidentally for machines to execute
стоп я запутался
1. вот юзер посылает чтото _send_data(dest,size1,buf1)
потом сразу же еще чото _send_data(dest,size2,buf2)
одному и томуже dest. как я должен теперь разрулить отправку через wsasend.
2. по поводу отправки размера и самих даных если я правильно понял то это — выдиляем новый буфер size+2, пишем в первые 2 байта размер, а потом копируем то что нужно послать и отправляем. тогда вопрос, может есть функция которой передается массив буферов и она ои отправляет за один раз, а то каждый раз выдилять/освобождать память для каждой посылки не очень как то. и кстате почему 2 байта на размер, что нельзя послать за раз больше 64кб?
... лучше почитать "Programming Server-Side Applications for Microsoft Windows 2000" на тему размера пула потоков, обслуживающих IOCP, и выноса длительной работы в другой пул/потоки.
Programs must be written for people to read, and only incidentally for machines to execute
B>стоп я запутался B>1. вот юзер посылает чтото _send_data(dest,size1,buf1) B> потом сразу же еще чото _send_data(dest,size2,buf2) B> одному и томуже dest. как я должен теперь разрулить отправку через wsasend.
> Накапавливаем исходящие сообщения в собственном буфере (в очереди) и отсылаем их по мере возможности (после успешного завершения очередной операции отправки).
B>2. по поводу отправки размера и самих даных если я правильно понял то это — выдиляем новый буфер size+2, пишем в первые 2 байта размер, а потом копируем то что нужно послать и отправляем. тогда вопрос, может есть функция которой передается массив буферов и она ои отправляет за один раз, а то каждый раз выдилять/освобождать память для каждой посылки не очень как то. и кстате почему 2 байта на размер, что нельзя послать за раз больше 64кб?
Вот алгоритм для чтения. Для записи будет похожий — тут уж лучше Вам самому подумать.
"Выделять буферы" вообще лишнее — используем один буфер и serializator + очередь ref-counted сообщений.
Programs must be written for people to read, and only incidentally for machines to execute
Здравствуйте, abrarov, Вы писали:
A> :) читали остальную часть моего сообщения
Читал. Проблемы не увидел, честно. Может проблема проявляется где-то, с чем-то я не сталкивался. Вот пишу я PortMapper (прокси), там на сокете одновременно передача и приём. Проблем нет.
A>или хотя бы Network Programming for Microsoft Windows?
Читал. Где конкретно там описаны трудности?
A>То, что сокет дуплексный, не подразумевает, что один и тот же сокет можно безопасно использовать одновременно из нескольких потоков.