Проблема MTU (Maximum Transmission Unit)

vova_php

Новичок
Здравствуйте. Столкнулся с проблемой, а именно - MTU.
Есть скрипт, который слушает udp порт и получает-отправляет данные.
Для отправки данных клиенту используется функция stream_socket_sendto, все данные отправляются сразу, 1-м выовом stream_socket_sendto. Иногда доходят не все данные ( человек сказал, что это связанно с ограничение MTU, у нас пакет весит ~3700 байт) .
Когда отправляешь данные порциями (вызов stream_socket_sendto идёт несколько раз), то опять не всем данные доходят.
Пожалуйста, подскажите как обойти?
 

Yaponchick

Новичок
1) Глянь какие данные доходят, и есть ли пакеты пришедшие с размером более MTU
2) На то он и UDP, чтобы не гарантировать доставку
 

MiksIr

miksir@home:~$
Полюбому такие большие UDP пакеты не есть хорошо. Даже если проблема не в MTU - то такие пакеты будут фрагментироваться (на 3 пакета), потеря одного фрагмента, ясно дело, убивает весь пакет.
Проблема с MTU может быть если используется Path MTU discovery, в этом случае, в теории, у вас на сокете вы сможете через socket_last_error прочесть ошибку EMSGSIZE, на практике в php не проверял как это работает. Можно попробовать отключить Path MTU discovery - в вашей ОС или на сокет IP_MTU_DISCOVER.
Но лучше думать о том, как ваш пакет побить на кусочки самому.
 

vova_php

Новичок
1) Глянь какие данные доходят, и есть ли пакеты пришедшие с размером более MTU
2) На то он и UDP, чтобы не гарантировать доставку
В том то и дело что если пакет меньше 1500 байт, то доходит.
Если больше этого злополучного MTU то не доходит.
Делаю так

Вариант 1
$packet = "\xff\xff\xff\xff\x66\x0a";
foreach($lmonitor as $f) $packet .= format_ip($f['server_ip'], $f['server_port']);
$packet .= format_ip("0.0.0.0", 0);
stream_socket_sendto($socket, $packet, 0, $peer);

Вариант 2
stream_socket_sendto($socket, "\xff\xff\xff\xff\x66\x0a", 0, $peer);

$packet = '';
foreach($lmonitor as $f) $packet .= format_ip($f['server_ip'], $f['server_port']);
stream_socket_sendto($socket, $packet, 0, $peer);

stream_socket_sendto($socket, format_ip("0.0.0.0", 0), 0, $peer);
 

vova_php

Новичок
Полюбому такие большие UDP пакеты не есть хорошо. Даже если проблема не в MTU - то такие пакеты будут фрагментироваться (на 3 пакета), потеря одного фрагмента, ясно дело, убивает весь пакет.
Проблема с MTU может быть если используется Path MTU discovery, в этом случае, в теории, у вас на сокете вы сможете через socket_last_error прочесть ошибку EMSGSIZE, на практике в php не проверял как это работает. Можно попробовать отключить Path MTU discovery - в вашей ОС или на сокет IP_MTU_DISCOVER.
Но лучше думать о том, как ваш пакет побить на кусочки самому.
Выше привел код. Пожалуйста помогите 3 суток, думаю срочно нужно найти решение. Весь поиск перерыл.
 

MiksIr

miksir@home:~$
Если есть возможность порезать пакеты в приложении и на другом конце их склеить - то так и нужно делать.
Попробуйте еще socket_set_option($socket, 0, 10, 0)
 

vova_php

Новичок
Если есть возможность порезать пакеты в приложении и на другом конце их склеить - то так и нужно делать.
Попробуйте еще socket_set_option($socket, 0, 10, 0)
ПРиложение которое принимает пакет от скрипта, оно не может резать.Нету исходников его.
 

MiksIr

miksir@home:~$
Тогда остается только играться с IP_MTU_DISCOVER как я показал в socket_set_option, но мог ошибиться в числах (констант таких в PHP нет). Ось, где PHP крутится, надеюсь, Linux?
 

vova_php

Новичок
Тогда остается только играться с IP_MTU_DISCOVER как я показал в socket_set_option, но мог ошибиться в числах (констант таких в PHP нет). Ось, где PHP крутится, надеюсь, Linux?
Да)Убунту.
Смысл такой.В базе находяться ip адреса. Человек открывает программу нажимает кнопку получить ip из базы они ему выдаются.
Так вот за раз можно 200 ip отправить.
А в базе их у меня больше 400 может чуть больше.Если слать ровно 200 из базы то скрипт работает и программа принимает. А как сделать что бы на программу шли несколько запросов?Ну допустим первые 200 Ip ушли на программу, потом вторые 200 ушли и так всю базу передавать)
Можно пример кода.Мои задумки я выложил сверху не получаеться у меня.С Вашими щас попробую.
 

faraun

Новичок
Попробуйте использовать функцию stream_socket_sendto() c флагом STREAM_OOB :
stream_socket_sendto($fp,$query,STREAM_OOB);
 

fixxxer

К.О.
Партнер клуба
не
надо
слать
по udp
пакеты размером
больше mtu
!!!1
 
  • Like
Реакции: craz

MiksIr

miksir@home:~$
fixxxer может ты еще 100% гарантированно скажешь размер MTU на всем пути от одного хоста к другому?
 

MiksIr

miksir@home:~$
А ты типа если нечего сказать по теме - лучше помолчи. Тут не ЖЖ тупые коменты оставлять.
 

craz

Нестандартное звание
А ты типа если нечего сказать по теме - лучше помолчи. Тут не ЖЖ тупые коменты оставлять.
ты давай меня не будешь так то опускать? ты в курсе что между хостами активное и посивное оборудование стоит? На любом из них можно определить размер блока. Так что теоритически все можно.


P.s. Заебли вы умничать неподелу... Даже если я написал куйню - это форум, поправь, подскажи и иди дальше, че ты ху...ми меришься?

UP: Максимальный размер блока между хостами равен минимальному установленному, на всем пути следования пакета, значению на оборудовании пропускающему udp. Если не прав, поправь.
 

MiksIr

miksir@home:~$
А ты как бы и не спрашивал. Спросил бы - ответил.
Стандартный MTU - 1500, но если где-то есть тунели, например, банально клиент по vpn цепляется к своему прову - MTU может уменьшаться (так как от пакета откусывается кусок данных для хранения служебной информации).
Пакеты которые не влезают в MTU - дефрагментируются. Но есть и другая технология - определение MTU пути, когда пакет отсылается с флагом "не фрагментировать" и если приходит отлуп "не влезает", то софту это сигнал уменьшать размер пакета.
А вот ткнуть пальцем сидя дома и сказать что-то 640 хватит всем 1400 пролезет везде - немного безответственно.
 

MiksIr

miksir@home:~$
UP: Максимальный размер блока между хостами равен минимальному установленному значению на оборудовании пропускающему udp. Если не прав, поправь.
Все верно. Сидя на сервере ты не можешь знать через какое оборудование это пойдет к клиенту. Если мы говорим, конечно, не об установленном туннеле к клиенту или локальной сети.
 
  • Like
Реакции: craz

craz

Нестандартное звание
А ты как бы и не спрашивал. Спросил бы - ответил.
Стандартный MTU - 1500, но если где-то есть тунели, например, банально клиент по vpn цепляется к своему прову - MTU может уменьшаться (так как от пакета откусывается кусок данных для хранения служебной информации).
Пакеты которые не влезают в MTU - дефрагментируются. Но есть и другая технология - определение MTU пути, когда пакет отсылается с флагом "не фрагментировать" и если приходит отлуп "не влезает", то софту это сигнал уменьшать размер пакета.
А вот ткнуть пальцем сидя дома и сказать что-то 640 хватит всем 1400 пролезет везде - немного безответственно.
Согласен полностью. Вот так бы сразу)
 

craz

Нестандартное звание
MiksIr
Ну значит мое сомнение в твоей адекватности было просто мимолетной слабостью)
 
Сверху