![]() |
Модераторы: feodorv |
![]() ![]() ![]() |
|
Artemon |
|
|||
а ты мне нравишься ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1771 Регистрация: 24.2.2004 Где: Челябинск Репутация: 1 Всего: 20 |
Стоит задача написать многопоточный UDP сервер (именно UDP)
Много клиентов и каждый шлет на сервер сложную структуру данных, а затем сервер отвечает на это сообщение. Если я буду в цикле через recvfrom принимать данные, то наткнусь на следующую ситуацию: Пришла какая-то часть данных одного клиента, а за ней часть данных от другого клиента и не будет возможности их отделить. Пришла в голову мысли получать IP пакет и собирать из них полное сообщение, а уж затем обрабатывать. У кого какие мысли ? -------------------- Контроль топлива на топливозаправщиках, мониторинг автотранспорта, расчет зарплаты водителей www.rscat.ru |
|||
|
||||
SVN74 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 740 Регистрация: 5.5.2008 Где: Комсомольск на Дн епре Репутация: 1 Всего: 18 |
UDP - ненадежный протокол и слать через него "сложную структуру" нежелательно. Почему бы не использовать TCP ? Конечно полной 100% -ой гарантии нет, но все же надежней будет ...
|
|||
|
||||
Олег2005 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 421 Регистрация: 26.5.2005 Где: Рига Латвия Репутация: 6 Всего: 11 |
Надо представлять логику предачи по UDP и работы recvfrom () Передатчик шлет одну датаграмму, в которой есть все что надо. Приемник с помощью recvfrom () получает ту полную датаграмму, которую послал передатчик. Он никогда не получит ее часть. Только всю целиком - но только данные. Вся адресная часть останется в модуле стека. Поэтому после recvfrom() следует выполнить getpeername() и получить адрес клиента, с которого пришел ответ, завести список всех клиентов и соединять данные по отдельным клиентам. Примерно так |
|||
|
||||
Artemon |
|
||||
а ты мне нравишься ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1771 Регистрация: 24.2.2004 Где: Челябинск Репутация: 1 Всего: 20 |
Да, TCP очень четко работает и нет никаких потерь + знаю от какого клиента идут пакеты, но в моей задаче получается так, что заголовок TCP пакета получается еще больше чем сами данные, поэтому КПД очень низок. Из-за этой причины решил использовать UDP.
Хочешь сказать, что если два клиента примерно в одно время пошлют по 1600 байт информации - есть гарантия, что придет полностью один из блоков в 1600 байт, а затем следующий блок в 1600 байт, но ни как не перемешанная информация ? Обратите внимание, я не спроста написал 1600, в большинстве сетей MTU ~ 1500. -------------------- Контроль топлива на топливозаправщиках, мониторинг автотранспорта, расчет зарплаты водителей www.rscat.ru |
||||
|
|||||
Олег2005 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 421 Регистрация: 26.5.2005 Где: Рига Латвия Репутация: 6 Всего: 11 |
Первый же маршрутизатор фрагментирует ваш UDP - пакет - на 2 IP- пакета. Модуль IP приемника дефрагментирует и выдаст на гора те же 1600 байт. Но если один фрагмент придет не вовремя - весь пакет отбросится - или будет обрезан - это зависит от конкретной реализации стека. |
|||
|
||||
Artemon |
|
|||
а ты мне нравишься ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1771 Регистрация: 24.2.2004 Где: Челябинск Репутация: 1 Всего: 20 |
Плохо конечно что не принятые данные обрезаются, это говорит о том, что мы не можем использовать разный размер буфера.
Думаю остается способ собирать IP пакеты воедино, а затем обрабатывать, кто-нибудь делал подобное ? -------------------- Контроль топлива на топливозаправщиках, мониторинг автотранспорта, расчет зарплаты водителей www.rscat.ru |
|||
|
||||
Comm |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 269 Регистрация: 31.8.2007 Где: Санкт-Петербург Репутация: -1 Всего: 1 |
А почему бы в этой структуре данных заодно и не послать идентификатор клиента и пакета.. Этим можно частично побороть не надежность UDP протокола. Допустим пришел пакет с данными от клиента с идентификатором пакета "2" сервер делает проверку есть ли от этого клиента пакет номер "1" если нет то шлет запрос на повторную отправку первого пакета итд. итп. -------------------- =))))) ![]() |
|||
|
||||
Олег2005 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 421 Регистрация: 26.5.2005 Где: Рига Латвия Репутация: 6 Всего: 11 |
Какой буфер вы имеете в виду? Обрезка идет в приемном буфере модуля UDP - а его можно выставить существенно большим, чем 64 к - опция SO_SNDBUF Как уже говорилось, опции SO_RCVBUF и SO_SNDBUF позволяют приложению изменять размеры буферов, заданные по умолчанию, которые для различных реализаций очень отличаются. В Беркли-реализациях по умолчанию используются буфера отправки и приема размером в 4096 байт, более современные системы используют буфера размером от 8192 до 61 440 байт. Размер буфера отправки UDP по умолчанию обычно около 9000 байт, если узел поддерживает NFS; а размер приемного буфера UDP — около 40 000 байт, а максимальное значение по умолчанию может достигать и 250Кб. |
|||
|
||||
kolobok0 |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 64 Регистрация: 24.12.2008 Репутация: нет Всего: 2 |
Вам уже написали решение. 1) собирать ничего не нуна. пакет либо прийдёт весь либо не прийдёт - третьего не дано. (CRC считаеться по всему пакету, дефрагментация идёт на IP уровне в толще самого стэка, вы об этом нифига не разумете если не сами автор этого стэка) 2) протокол TCP использует заголовок достаточно маленький при больших объёмах. Шлите не 50 байт а 50 мегабайт и будет вам копейки. Либо держите канал открытым. 3) Если всё таки UDP - тут уже правильно всё сказали. используйте свои маркеры сессий, пользователя и прочей лабуды. Очень рулит при таком подходе - юзанье "чёрного ящика" на стороне клиента от сервера. а сервер трактует этот "чёрный ящик" как свои данные..Нечто аля куки или сешшион под HTTP.. удачи Вам (круглый) |
|||
|
||||
![]() ![]() ![]() |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Сети | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |