| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Сети > Дуплексная передача по сокету |
| Автор: Finalist 1.8.2013, 14:31 | ||
| Приветствую всех! Сейчас использую такую схему приемо-передачи данных клиент-сервер: каждый клиент подключается к серверу дважды.. после рукопожатия отмечает сокеты как приемный и передающий.. в один сокет пишет он серверу, по второму сервер пишет клиенту. таким образом есть возможность серверу быть инициатором команд.. все работает прекрасно, нет никаких проблем. Вчера появился в голове вопрос.. возможно ли сделать такую схему на одном сокете? Не будет ли коллизии при отсылке пакетов от клиента к серверу и наоборот? Накидал два проектика со схемой одного сокета. снифером пытался пронюхать.. есть ошибки приема.. хочу получить подтверждение того что эта схема не работает! В снифере вот такой результат:
|
| Автор: Finalist 1.8.2013, 18:35 | ||
| Переписал немного тестовые программки... отсылаю не просто ААА в одну сторону и ВВВ в другую, а теперь шлю в обе стороны по очереди 111, 222, 333, 444, 555 и так далее... снифаю порт: получаю нормальную очередность, но иногда приходят пустые пакеты.. а иногда два пакета склеены в один. так что, вопрос снят. Если у кого-то есть соображения по этому поводу, прошу говорить! мне эта тема очень интересна и важна.
|
| Автор: 1Nikita 1.8.2013, 22:09 |
| Я вот думаю, можно ли перекачивать воду по одной трубе в обе стороны одновременно(полный дуплекс)? |
| Автор: Finalist 2.8.2013, 10:26 |
Благодарю! теперь буду делать только так. |
| Автор: 1Nikita 2.8.2013, 11:37 | ||
Полудуплекс или полный дуплекс? Если полный, то каким образом отделить в памяти принятые пакеты от отправляемых? порт то один. |
| Автор: Finalist 2.8.2013, 13:10 | ||
Можешь что нибудь конкретно сказать? камни подводные может знаешь? |
| Автор: feodorv 2.8.2013, 17:35 | ||
Гм. Есть большое желание отправить книжки читать))) На самом деле так сокеты и планировались - полнодуплексными. Порт один, да, но и сокет один, полнодуплексности это никак не мешает. Просто где-то на транспортном уровне формируются отдельные очереди на приём и передачу. Очередь на приём считывается вызовами recv/recvfrom/read, очередь на передачу формируется вызовами send/sendto/write. И всё это на одном и том же сокете. На канальном уровне уже полнодуплесность может отсутствовать (а может и нет), например, в один и тот же момент времени по кабелям может передаваться только один пакет и только в одну сторону. Но и тогда пакеты передаются с бешеной скоростью, то в одну сторону, то в другую, чем, собственно, и обеспечивается одновременная (с точки зрения приложения) передача данных в обе стороны. Никакого водопровода. Посмотрите на описание функции select (или если дело происходит в рамках WinAPI, то WSAWaitForMultipleEvents). Убедитесь, что функция способна обеспечить (даже асинхронную) обработку данных в обе стороны - на приём и на передачу на одном единственном сокете. Никакого мошенничества Подводные камни встречаются повсюду, но нужно знать реку/залив/гавань, в которой Вы плаваете. Всё сильно зависит от задачи и используемого API. |
| Автор: 1Nikita 2.8.2013, 20:00 | ||
Ну вот ты скажи тогда, раз порт один то и приёмник и буфер для отправки находятся по одному адресу в памяти. Нам нужно отправить 10 байт в сеть , мы записываем их в порт (send), и тут же из сети приходят пакет 10 байт и тоже попадает в этот порт и нам нужно их считать (recv). И как отделить мух от котлет? С полудуплексом всё понятно,ибо он переключается с приёма на передачу и обратно (типа радиостанции). |
| Автор: feodorv 2.8.2013, 20:47 | ||
Буферы разные. Один - на приём, другой - на передачу. Что здесь непонятного? |
| Автор: 1Nikita 3.8.2013, 12:05 | ||||
Если порт один, то и буфер тоже один,в зависимости от того действия которое происходит. Мы сейчас говорим о сокетах, а не о том как реализуется передача данных на других более низких уровнях. И вопрос, кстати, был о дуплексности сокетов. Каким образом ты запишешь в порт (send) и считаешь (recv) оттуда данные одновременно??? ведь полнодуплексный режим именно так работать должен. Даже если делать через события, то всё равно получается полудуплекс, но не полный. Еще раз привожу пример с трубой, как по одной трубе ты перекачаешь воду в двух направлениях одновременно? Либо нужна вторая труба, а это уже другой сокет, либо по очерёдности качаю то в одну то в другую сторону, а это уже ПОЛУдуплекс. |
| Автор: feodorv 3.8.2013, 14:06 |
Ну вот что за упёртость)))) Почему буфер один??? Что мешает завести два (а то и более) буфера? С пользовательской точки зрения У открываемого сокета создаются два буфера - на приём и передачу. В буфер на приём складываются данные, которые пользовательское приложение отправляет в сеть, эти данные могут быть тотчас отправлены, а могут и с задержкой, а то и не отправлены совсем (сеть перегружена или вообще вышла из строя). В буфер на приём складываются данные, которые приходят из сети, и которые должны быть считаны пользовательским приложением, иначе буфер приёма забьётся, и более туда ничего поместить не получится - пришедшие данные будут потеряны. С помощью вызова setsockopt сокету раздельно можно задать размеры этих двух буферов: SO_RCVBUF - для буфера приёма, SO_SNDBUF - для буфера передачи. Можно изловчиться и на одном и том же порту открыть несколько сокетов, у каждого из которых будут свои буферы приёма-передачи, и они не будут друг другу мешать ни коим образом. С точки зрения ОС Каждый приходящий из сети пакет http://paramax.susu.ru/study/tcpips/-Obzor_TCP-IP-Demulmztipleksirovanie_prinimaemyh_dannyh.htm до пользовательского сокета и кладётся в его буфер приёма. Каждая порция пользовательских данных из буфера передачи аккуратно завёртывается в пакет, который затем уходит в сеть. Я больше скажу. Реально нет никаких статических буферов, есть очереди буферов (которые позволяют избежать лишнего копирования данных). Почитайте хотя бы про mbuf. И срочно читать http://yandex.ru/yandsearch?text=%D1%81%D1%82%D0%B8%D0%B2%D0%B5%D0%BD%D1%81%20%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0%20%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D1%8B%D1%85%20%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&clid=48648&lr=213. Пока не прочтёте, лучше не делайте поспешных выводов. |
| Автор: feodorv 3.8.2013, 14:25 |
У одного единственного сокета две трубы, вот так |
| Автор: 1Nikita 4.8.2013, 20:25 | ||
Если две трубы то это уже симплект по каждой из них |
| Автор: feodorv 4.8.2013, 21:35 | ||
Честно, не математик, и юмора не понял Ну подумайте сами, какая может быть причина для того, чтобы пользоваться одним единственным буфером со всеми вытекающими отсюда неудобствами? Вон у FILE один единственный буфер, по, вполне, кстати, понятным причинам, так каким же нужно быть осторожным, когда переходишь от чтения к записи или от записи к чтению. А у сокета? Да без проблем:
и все проблемы с полнодуплексностью ложатся на сеть. Удобно же. А сколько бы крику было по разным форумам, если бы буфер был один. Так и вижу темы: "Потеряны пакеты при отправке в сокет???" с однотипными ответами "Так нужно было дождаться полного приёма присылаемых данных, а уж потом туда записывать!" и т.д. Два буфера реализуются легко, поддержки по синхронизации не требуют, схема работы с сокетом сразу упрощается, автоматом получается полнодуплексность. Красота |
| Автор: 1Nikita 5.8.2013, 14:27 |
| В предыдущем посте сделал описку, следует читать "СИМПЛЕКС". Это не из математики (хотя и там есть), симплекс (телевизионный сигнал), полудуплекс (радиостанция), полныйдулекс (двусторонее движение автомобилей по одному полотну одновременно в обе стороны). А с сокетами трубы то две получается. Меня этот момент интерисовал. PS ты вот модератор, а по этому вопросу http://forum.vingrad.ru/forum/c-c++network.html есть у тебя какие нибудь мысли? |
| Автор: feodorv 5.8.2013, 15:03 |
А, это из связи, понял Модератор - тоже человек, всего знать не может. Очень сложный http://book.itep.ru/6/tls.htm, если честно, должны http://en.wikipedia.org/wiki/Transport_Layer_Security какие-нибудь библиотеки для упрощения реализации, я так думаю. |
| Автор: 1Nikita 5.8.2013, 20:29 | ||||
Сложностей там нет. Библиотеки есть в составе винды, реализовывать эти алгоритмы не надо. А если и надо было, то реализация всех алгоритмов есть в интернете на С. Только как их (TLS) юзать непонятно. |
| Автор: SVN74 6.8.2013, 22:40 |
| Ничего не надо изобретать... Заведите два потока один на приемку, другой на отправку и увидите на что способен сокет... |
| Автор: feodorv 7.8.2013, 00:42 | ||
А чем один-единственный поток плох в демонстрационных целях? |
| Автор: SVN74 7.8.2013, 11:32 |
Про экспериментируйте, что быстрей работает? Один поток: send(Любой текст); recv(Любой текст); send(Любой текст); recv(Любой текст); send(Любой текст); recv(Любой текст); и т.д. ( в цикле) Или Два потока: Thread1 -> send(Любой текст) Thread2-> recv(Любой текст) (в циклах) В потоках скорость в несколько раз выше. |
| Автор: feodorv 7.8.2013, 12:56 |
Ну так надо пользоваться асинхронной моделью. В синхроне-то понятно, что медленнее. |
| Автор: Finalist 4.9.2013, 17:39 |
| http://habrahabr.ru/post/192284/ с завтрашнего дня начинаю тесты Boost::Asio но у меня возник интереснейший вопрос - как мне выбрать порт для сервера игры? понимаю что вопрос немного причудлив, но хотелось бы услышать интересную историю по поводу выбора порта для своей игры)) если кто знает нюансы - пишите! |
| Автор: feodorv 4.9.2013, 19:13 | ||||
Ну, эээ...
(взято http://ru.wikibooks.org/wiki/%D0%9F%D0%BE%D1%80%D1%82) Но я бы всё же проверил, не используется ли понравившийся порт http://ru.wikipedia.org/wiki/%D1%EF%E8%F1%EE%EA_%EF%EE%F0%F2%EE%E2_TCP_%E8_UDP... |