Склеиваются пакеты. Как отключить Nagle-алгоритм?

Обсуждения по программированию для ОС Windows безотносительно используемого языка программирования. Windows NT, Win32, Windows API, ядро и драйверы.
AWPStar
Начинающий
Начинающий
 
Сообщения: 16
Зарегистрирован: 29.07.2010 (Чт) 2:32

Склеиваются пакеты. Как отключить Nagle-алгоритм?

Сообщение AWPStar » 28.09.2015 (Пн) 20:26

Не уверен, что это только к Windows относится, но всеже напишу тут.
Никак не получается в TCP-сокете отключить алгоритм Нейгла.

Делаю через setsockopt
По MSDN значение TCP_NODELAY должно передаваться как Boolean? т.е. 2 байта
В клиенте(для теста использую winsock), после соединения прописываю:
Код: Выделить всё
setsockopt Winsock1.SocketHandle, SOL_SOCKET, TCP_NODELAY, True, 2&

В сервере делаю тоже самое, сразу после создания сокета(NewSocket = Socket(2, 1, 6))

Пакеты все равно приходят склеенные. Как это правильно сделать?
На UDP не хотелось бы переходить, т.к. многое придется переписывать.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 29.09.2015 (Вт) 12:10

Во-первых, скорее всего не True, а 1.
Во-вторых, а ты уверен, что Boolean - это 2 байта, а не 1 и не 4?

AWPStar
Начинающий
Начинающий
 
Сообщения: 16
Зарегистрирован: 29.07.2010 (Чт) 2:32

Re:

Сообщение AWPStar » 29.09.2015 (Вт) 12:36

Qwertiy писал(а):Во-первых, скорее всего не True, а 1.
Во-вторых, а ты уверен, что Boolean - это 2 байта, а не 1 и не 4?

Надо сказать да, там DWORD (boolean), я сразу не заметил.
Но в любом случаи таже ситуация. Пакеты склеиваются.

Не может быть это из-за того, что я как-то криво принимаю пакеты?
Код: Выделить всё
reBytes = recv(IncSocket(reIndex), reData, BuffSize, 0)
Не знаю, правда, где тут ошибиться можно

AWPStar
Начинающий
Начинающий
 
Сообщения: 16
Зарегистрирован: 29.07.2010 (Чт) 2:32

Re: Склеиваются пакеты. Как отключить Nagle-алгоритм?

Сообщение AWPStar » 15.10.2015 (Чт) 15:55

В общем я забил на TCP и решил юзать UDP.

И тут я получил затык.
С помощью recv данные нормально получаются, но не узнать IP отправителя.
А recvfrom возвращает -1, причем бесконечно, в цикле, пока программу не убьешь. WSAGetLastError выдает 0. В МСДН такого кода ошибки нету. При этом указанно, что если recvfrom принимает отрицательные значения, то это ошибка и надо искать через WSAGetLastError.


solved

не знаю почему, но последний параметр у sendto передается как значение размера структуры, а у recvfrom именно как указатель о_О. Бред майкросовтовский...
З.Ы. Дикларированны обе были как ByVal. Вот и понять не мог этот беспредел.

Вынос мозга
Изображение



Если кому интересно, вот готовый контрол UDP-сокета:

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Склеиваются пакеты. Как отключить Nagle-алгоритм?

Сообщение Хакер » 15.10.2015 (Чт) 21:30

AWPStar писал(а):В общем я забил на TCP и решил юзать UDP.

Звучит крайне странно. У TCP и UDP разные задачи, разные области применения, разные плюсы и минусы. Как можно с ними обращаться в стиле: «с одним так и не разобрался, попробую другое»?

AWPStar писал(а):Бред майкросовтовский...

Бред твой.

Аргумент объявлен с таким типом по самым необходимым причинам. Как ещё он функция может вернуть возвращающей стороне размер возвращённого буфера, если не через ByRef-аргумент. Ты сам-то хоть думаешь? Всё сделано правильно.

Причём тут ты сел в лужу вдвойне, потому что сетевые функции в Windows совпадают с сетевыми API почти во всех прочих операционных системах. И в Linux-подобных ОС есть та же самая recvfrom с теми же точно аргументами с такими же точно типами. И все они работают одинаково.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

AWPStar
Начинающий
Начинающий
 
Сообщения: 16
Зарегистрирован: 29.07.2010 (Чт) 2:32

Re: Склеиваются пакеты. Как отключить Nagle-алгоритм?

Сообщение AWPStar » 15.10.2015 (Чт) 21:51

Хакер писал(а):Как можно с ними обращаться в стиле: «с одним так и не разобрался, попробую другое»?
Мне нужно было передавать данные. В TCP они склеивались пакетами. Отключение алгоритма Нейгла не помогло. решения я не нашел. Решил использовать UDP. Так и можно. Это не машину себе выбирать и не сервер для MMO писать.

Хакер писал(а):Бред твой.
Мы на личности переходим? Что за гонор, да еще и от Администратора?

Хакер писал(а):Аргумент объявлен с таким типом по самым необходимым причинам. Как ещё он функция может вернуть возвращающей стороне размер возвращённого буфера, если не через ByRef-аргумент. Ты сам-то хоть думаешь? Всё сделано правильно.
Я думаю. Это input-аргумент. Он передает значение, а не возвращает. Это не размер буфера. Это размер структуры, который передается функции. Причем, постоянный, в 16 байт. Передавать его значением в sendto, а в аналогичной процедуре recvfrom указателем - минимум не логично.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Склеиваются пакеты. Как отключить Nagle-алгоритм?

Сообщение Хакер » 16.10.2015 (Пт) 4:10

AWPStar писал(а):В TCP они склеивались пакетами.

Ну и что?
Кому какое дело, что там происходит с пакетами в случае с TCP?
TCP передаёт стрим. То есть поток. Подобному тому, как это делает пайп на локальной машине.
Если нужно передавать «просто данные» — значит нужно использовать TCP.
Если нужно передавать какие-то свои пакеты через TCP, значит нужно придумать для этих пакетов соответствующие заголовки, а на принимающей стороне резать стрим на пакеты, ориентируясь на заголовки.

А UDP шлёт единичные датаграммы. Не давая никакой гарантии ни на счёт того, придёт ли каждая из датограмм получателю вообще (могут не прийти), ни на счёт того, в каком порядке они придут (могут прийти в совершенно запутанном порядке, по сравнению с порядком отправки), ни на счёт того, что единожды посланная датаграмма придёт получателю однократно (1 датаграмма может быть получена принимающей стороной хоть 20 раз). Все эти проблемы должен решать софт. Вернее, немного иначе. Разработчик должен выбирать UDP только тогда, когда все эти проблемы — не совсем уж и проблемы (зато максимально быстрая доставка и минимальные издержки — гораздо более важные аспекты передачи данных).

AWPStar писал(а):Мы на личности переходим? Что за гонор, да еще и от Администратора?

Разве я что-то сказал насчёт твоей личности? По-моему я только высказался насчёт твоего бреда. А бред был.
И потом, это ты сам начал развешивать ярлыки и сыпать оскорбления в адрес неизвестных программистов. Не стоило тебе этого делать. Не нравится ведь самому в свой адрес такое слышать?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Склеиваются пакеты. Как отключить Nagle-алгоритм?

Сообщение Хакер » 16.10.2015 (Пт) 4:23

AWPStar писал(а):Я думаю. Это input-аргумент. Он передает значение, а не возвращает. Это не размер буфера.

Ты неправильно думаешь. Дважды неправильно.

Это не input-аргумент. Это input/output-аргумент в случае recvfrom.

Через него передаётся указатель на ячейку памяти, которая на входе содержит размер буфера, предоставленного вызывающей стороной под запись адресной структуры.
На выходе из функции туда записывается количество реально записанных байтов.

Это не буфер под данные, верно, но это буфер (произвольного размера), куда функция запишет адрес, вернее структуру, кодирующую адрес. Поскольку может использоваться разная адресация, может быть использовано множество разных sockaddr-структур разного размера (под IPv4 — одна структура с одним размером, под IPv6 — другая структура с другим размером, под ещё какой-то протокол, над которым тоже можно инкапсулировать UDP — ещё какая-то третья структура со своим размером).

Поэтому функция сделана именно так, чтобы программист мог скормить ей заведомо большой буфер и при этом иметь возможность сообщить функции, насколько велик этот буфер, чтобы функция не вышла случайно за его пределы, записывая туда данные, а после возврата мог как-то посмотреть, сколько именно было записано. Это буфер не под данные, а под адрес, который записывается в виде структур, имеющих разную структуру, в зависимости от используемого уровнем ниже протокола.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

AWPStar
Начинающий
Начинающий
 
Сообщения: 16
Зарегистрирован: 29.07.2010 (Чт) 2:32

Re: Склеиваются пакеты. Как отключить Nagle-алгоритм?

Сообщение AWPStar » 16.10.2015 (Пт) 12:37

Хакер писал(а):Это не буфер под данные, верно, но это буфер (произвольного размера), куда функция запишет адрес, вернее структуру, кодирующую адрес. Поскольку может использоваться разная адресация, может быть использовано множество разных sockaddr-структур разного размера (под IPv4 — одна структура с одним размером, под IPv6 — другая структура с другим размером, под ещё какой-то протокол, над которым тоже можно инкапсулировать UDP — ещё какая-то третья структура со своим размером).

Поэтому функция сделана именно так, чтобы программист мог скормить ей заведомо большой буфер и при этом иметь возможность сообщить функции, насколько велик этот буфер, чтобы функция не вышла случайно за его пределы, записывая туда данные, а после возврата мог как-то посмотреть, сколько именно было записано. Это буфер не под данные, а под адрес, который записывается в виде структур, имеющих разную структуру, в зависимости от используемого уровнем ниже протокола.


Т.е., в теории, если я создал сокет, привязал его в IPv4-адресу(к примеру), то кто-то может на него послать пакет IPv6-стандарта? Не думал, что это возможно, т.к. адресация другая.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16473
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Склеиваются пакеты. Как отключить Nagle-алгоритм?

Сообщение Хакер » 16.10.2015 (Пт) 12:40

AWPStar писал(а):Т.е., в теории, если я создал сокет, привязал его в IPv4-адресу(к примеру), то кто-то может на него послать пакет IPv6-стандарта? Не думал, что это возможно, т.к. адресация другая.


Даже без этого. Просто представь, что у программиста есть функция-обёртка над recvfrom. Эта функция обёртка не знает, как именно был создан — его предысторию. Она не знает, какая адресация используется. Но ей надо как-то получить структуру. При этом она сама выделяет буфер под неё. Какого размера ей буфер выделять?

И вообще, это стандартная практика: функции, которые заполняют предоставленную им память, просят на вход максимальный размер буфера, а на выходе сообщают, сколько именно они записали.

Правила хорошего тона диктуют, что и операции записи в буфер и операции чтения из него защищены проверкой за выход за границу доступного буфера / границу корректных данных.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

AWPStar
Начинающий
Начинающий
 
Сообщения: 16
Зарегистрирован: 29.07.2010 (Чт) 2:32

Re: Склеиваются пакеты. Как отключить Nagle-алгоритм?

Сообщение AWPStar » 16.10.2015 (Пт) 13:42

Понятно. Я думал, что последние 8 пустых байт(в структуры для IPv4) выделены для запаса как раз на случай использования других протоколов. Посмотрю, что будет если их убрать и передавать всего 8 байт.
(ред.) С 8 не работает. Не понятно зачем они тогда выделены в IPv4.

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: Склеиваются пакеты. Как отключить Nagle-алгоритм?

Сообщение iGrok » 18.10.2015 (Вс) 0:19

AWPStar писал(а):С 8 не работает.

Конечно не работает. Структура-то 16-байтная.

AWPStar писал(а):Не понятно зачем они тогда выделены в IPv4.

sin_zero Padding to make structure the same size as SOCKADDR.

Зачем это - можно почитать в описании SOCKADDR. В целом что-то типа "так сложилось исторически".
label:
cli
jmp label


Вернуться в Windows-программирование

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 9

    TopList