Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Сети > Порядок байт и битовые операции. |
Автор: konshyn 6.8.2014, 16:29 | ||
Ребят, нет возможности проверить (ни одной машины нет с нужным порядком байт) У меня на машине little-endian порядок байт, сетевой порядок байт - big-endian. Так вот, хочу работать с заголовками с помощью битовых операций. Пример:
и я получаю именно тот порт, с которого была отправлена датаграмма. я так понимаю, с порядком big-endian на машине я получу такой же результат. но вот загвоздка, если у меня little-endian, то мне нужно опять использовать htons(), чтобы записать этот порт, к примеру, в sockaddr_in, а если big-endian - не нужно. Как сделать это элегентно, и с возможностью работать через битовые операции (намного удобнее, чем через всякие структуры и просто копирование. по крайне мере мне так нравится ![]() |
Автор: konshyn 6.8.2014, 18:19 | ||||
Почему неверено? Верно, дальше по тексту вы сами объясняете, что будет ![]()
Верно, но, к примеру, когда я принимаю через recvfrom() датаграмму, т.е. я туда еще отправляю структуру sockaddr_in, чтобы мне ядро скинуло ip-адрес отправителя, то этот ip-адрес записан в big-endian порядке. Жаль, что порт туда не записывается. хотя, структура sockaddr_in специально для AF_INET сделана, другими словами для TCP и UDP. они имеют поля портов на одном и том же месте в своем заголовке - в начале. логично было бы делать это. так вот, я бы хотел делать как писал выше, но для этого придется писать htons(), но, если я буду делать как делают все, то не нужно, т.к. они уже записаны в big-endian порядке. Думал-думал, как элегантно сделать, но не придумал...придется как всегда:(
|
Автор: feodorv 6.8.2014, 19:55 | ||||
Что Вы имеете в виду?
Всё записывается. Добавлено через 2 минуты и 58 секунд
|
Автор: konshyn 6.8.2014, 22:19 |
Я имел в виду из функции recvfrom() |
Автор: feodorv 6.8.2014, 23:22 |
И я имел в виду из функции recvfrom(). Приведённый код как раз выполняется после recvfrom [UDP]. |
Автор: konshyn 7.8.2014, 10:35 | ||||||||
У меня почему-то на сырой сокет порт не записывается
Добавлено через 1 минуту и 16 секунд отправляю пакет вот так:
|
Автор: tzirechnoy 7.8.2014, 13:15 |
http://commandcenter.blogspot.ru/2012_04_01_archive.html Добавлено через 3 минуты и 15 секунд Ровно обратным порядком: buffer[0] = post&0x0F; buffer[1] = (port >> 8)&0x0F; Впрочем, htons можно просто вставлять всегда. |
Автор: konshyn 7.8.2014, 14:06 |
можно, но: этот вариант намного красивей) |
Автор: feodorv 7.8.2014, 14:54 |
Гм. Сделайте честную отправку пакета через sendto. Что там с /dev/udp, я не знаю. |
Автор: konshyn 7.8.2014, 15:11 | ||||||
Вот код:
вот результат одно из пакетов:
Добавлено через 6 минут и 52 секунды Но если делать не сырой сокет, а обычный датаграммный (верхнуюю часть заменить на это)
то да, recvfrom пишет в sin_port номер порта, с которого пришел пакет. Все дело в сыром сокете. |
Автор: feodorv 7.8.2014, 21:53 |
Ага. Видимо, сетевой уровень в этом случае не разбирает датаграмму... |
Автор: konshyn 8.8.2014, 10:43 | ||
Но source IP записывает. |
Автор: feodorv 8.8.2014, 21:36 |
Гм. Значит, разбирает только до уровня заголовка IP))) Сырой сокет, однако))) Заметил в коде недочет. Переменная length_sock должна быть правильно инициализирована перед вызовом recvfrom. |
Автор: konshyn 9.8.2014, 13:04 | ||
С одной стороны - да. Так Стивенс писал. Но я не знаю, как в стандарте. Но все работает, т.к. в эту переменную записывается длина структуры, а не считывается. А если инициализировать так, как нужно, результат не меняется |
Автор: feodorv 9.8.2014, 15:47 | ||
Переменная обязана быть инициализирована. Она http://www.opennet.ru/man.shtml?topic=recvfrom&category=2&russian=2 коду recvfrom, сколько байт находится по адресу ipaddr, доступных для записи:
У Вас в переменной length_sock - мусорное значение, которое может оказаться подходящим для вызова recvfrom, а может и нет. Как минимум в виндах будет ошибка вызова, если передать неверное значение. В юниксах возможны варианты. |
Автор: konshyn 9.8.2014, 17:29 |
В linux не вызывает ошибки и работает. Понятно ![]() |