| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Сети > Получение IP пакетов |
| Автор: Artemon 6.2.2009, 19:33 |
| Стоит задача написать многопоточный UDP сервер (именно UDP) Много клиентов и каждый шлет на сервер сложную структуру данных, а затем сервер отвечает на это сообщение. Если я буду в цикле через recvfrom принимать данные, то наткнусь на следующую ситуацию: Пришла какая-то часть данных одного клиента, а за ней часть данных от другого клиента и не будет возможности их отделить. Пришла в голову мысли получать IP пакет и собирать из них полное сообщение, а уж затем обрабатывать. У кого какие мысли ? |
| Автор: SVN74 6.2.2009, 22:07 |
| UDP - ненадежный протокол и слать через него "сложную структуру" нежелательно. Почему бы не использовать TCP ? Конечно полной 100% -ой гарантии нет, но все же надежней будет ... |
| Автор: Artemon 7.2.2009, 20:31 | ||||
Да, TCP очень четко работает и нет никаких потерь + знаю от какого клиента идут пакеты, но в моей задаче получается так, что заголовок TCP пакета получается еще больше чем сами данные, поэтому КПД очень низок. Из-за этой причины решил использовать UDP.
Хочешь сказать, что если два клиента примерно в одно время пошлют по 1600 байт информации - есть гарантия, что придет полностью один из блоков в 1600 байт, а затем следующий блок в 1600 байт, но ни как не перемешанная информация ? Обратите внимание, я не спроста написал 1600, в большинстве сетей MTU ~ 1500. |
| Автор: Олег2005 9.2.2009, 00:20 | ||
Первый же маршрутизатор фрагментирует ваш UDP - пакет - на 2 IP- пакета. Модуль IP приемника дефрагментирует и выдаст на гора те же 1600 байт. Но если один фрагмент придет не вовремя - весь пакет отбросится - или будет обрезан - это зависит от конкретной реализации стека. |
| Автор: Artemon 9.2.2009, 11:48 |
| Плохо конечно что не принятые данные обрезаются, это говорит о том, что мы не можем использовать разный размер буфера. Думаю остается способ собирать IP пакеты воедино, а затем обрабатывать, кто-нибудь делал подобное ? |
| Автор: Comm 19.2.2009, 08:50 | ||
А почему бы в этой структуре данных заодно и не послать идентификатор клиента и пакета.. Этим можно частично побороть не надежность UDP протокола. Допустим пришел пакет с данными от клиента с идентификатором пакета "2" сервер делает проверку есть ли от этого клиента пакет номер "1" если нет то шлет запрос на повторную отправку первого пакета итд. итп. |
| Автор: Олег2005 19.2.2009, 12:52 |
Какой буфер вы имеете в виду? Обрезка идет в приемном буфере модуля UDP - а его можно выставить существенно большим, чем 64 к - опция SO_SNDBUF Как уже говорилось, опции SO_RCVBUF и SO_SNDBUF позволяют приложению изменять размеры буферов, заданные по умолчанию, которые для различных реализаций очень отличаются. В Беркли-реализациях по умолчанию используются буфера отправки и приема размером в 4096 байт, более современные системы используют буфера размером от 8192 до 61 440 байт. Размер буфера отправки UDP по умолчанию обычно около 9000 байт, если узел поддерживает NFS; а размер приемного буфера UDP — около 40 000 байт, а максимальное значение по умолчанию может достигать и 250Кб. |
| Автор: kolobok0 16.3.2009, 19:09 | ||
Вам уже написали решение. 1) собирать ничего не нуна. пакет либо прийдёт весь либо не прийдёт - третьего не дано. (CRC считаеться по всему пакету, дефрагментация идёт на IP уровне в толще самого стэка, вы об этом нифига не разумете если не сами автор этого стэка) 2) протокол TCP использует заголовок достаточно маленький при больших объёмах. Шлите не 50 байт а 50 мегабайт и будет вам копейки. Либо держите канал открытым. 3) Если всё таки UDP - тут уже правильно всё сказали. используйте свои маркеры сессий, пользователя и прочей лабуды. Очень рулит при таком подходе - юзанье "чёрного ящика" на стороне клиента от сервера. а сервер трактует этот "чёрный ящик" как свои данные..Нечто аля куки или сешшион под HTTP.. удачи Вам (круглый) |