powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как выжать весь гигабит по UDP?
25 сообщений из 162, страница 1 из 7
Как выжать весь гигабит по UDP?
    #38894066
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Наткнулся на странную проблему: виндовс7 медленно шлет UDP локалке. В гигабитной сети не могу 100 мбит перешагнуть, при том что теже 100 мбит получаю по внутрисети провайдера (запускаю прием дома в линуксе).
Физически: гигабитный роутер, к нему подключены все компы и инет. TCP дает гигабит (wget c локального HTTP сервера).

Алгоритм передачи следующий: отправитель шлет непрерывный набор пакетов (окно), получатель подтверждает прием первого пакета окна, отправитель получив подтверждение шлет следущее окно.

Окно от 32 пакетов. По локалке подтверждение приходит после отправки первого пакета, по внутри-инету после 5-10. Т.е. в обоих случаях поток получается непрерывный. При этом проц не загружен даже на 10%.

Увеличение окна (с 32 до 128) в локалке вообще никакого эффекта не дает, та же скорость. Оно понятно, т.к. подтверждение приходит после первого.

Подозреваю что надо еше какие-то флаги сокета поставить. Знать бы какие.

Такое впечатление что есть какая-то синхронность при отправке (иначе как получаю ответ после первого пакета неуспев второй отправить), может она как-то отключается?
Сейчас так происходит
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
SOCKET sock_udp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
// Установка размера буфера входящих пакетов
size =  3014656;
if (setsockopt(sock_udp, SOL_SOCKET, SO_RCVBUF, (char *) &size, sizeof(size)) == -1 ) {
...
}
// Установка запрета фрагментации пакетов
int yes = IP_PMTUDISC_DO;
if(setsockopt(sock_udp, IPPROTO_IP, IP_DONTFRAGMENT, (char *) &yes, sizeof(yes)) == -1 ) {
...
}
...
sockaddr_in addr_in;
...
if(bind(sock_udp, (SOCKADDR *) &addr_in, (socklen_t) sizeof(sockaddr_in)) != 0) {
...
}
...
// Отправка
size = sendto(sock_udp, msg, size_to_send, 0, (SOCKADDR *) &addr, sizeof(sockaddr_in));
...
// Прием
socklen_t addr_size = sizeof(sockaddr_in);
int size = recvfrom(sock_udp, msg, 1472, 0, (SOCKADDR *) &addr, &addr_size);



PS Завтра попробую на одном из компов линукс поднять, чтобы окончательно убедится что проблема именно в винде.
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894075
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,

Предположение:
TCP применяет congestion control и устанавливает оптимальную скорость отсылки, соответствующую физическому каналу.
А ваш протокол основанный на UDP не умеет этого, и вы отправляете пакеты слишком часто и они забивают канал (и возможно буфер отправки). В итоге большинство пакетов теряются.
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894076
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TПри этом проц не загружен даже на 10%.Это от 10% ядра или от всего проца? Сколько ядер?
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894078
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если слать через localhost, т.е. на одном компе отправитель и приемник, то получаю 800-900 мбит.
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894079
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoftDima TПри этом проц не загружен даже на 10%.Это от 10% ядра или от всего проца? Сколько ядер?
Ядра. всего 4. Проц i7 3.7 ГГц
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894083
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyА ваш протокол основанный на UDP не умеет этого, и вы отправляете пакеты слишком часто и они забивают канал (и возможно буфер отправки). В итоге большинство пакетов теряются.
Ни одного не теряется. Контроль потерь есть, логи и т.д.
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894089
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,

размер пакета?
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894225
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропилразмер пакета?
Максимальный. Содержимое UDP 1472 байта, в т.ч. полезные данные 1456 байт.
Тестовые 10240000 байт это 7033 пакетов.

Поправил отправку: окно теперь уходит в цикле. До этого была проверка входящих после каждого отправленного пакета. Отключил лишние логи. Получил ускорение на localhost, передача полезной инфы 131 мбайт/с (~1,3 гигабита), а по сетке стабильно 8-8,2 мбайт/с, до линукса 10 через инет (внутрисеть провайдера) :(

Пошел ставить линукс.
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894439
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoftDima TПри этом проц не загружен даже на 10%.Это от 10% ядра или от всего проца? Сколько ядер?

Гы, а почему проц вообще должен быть загружен? Ну да, что-то он там управляет, но нагрузка-то основаная тупо на сеть.
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894512
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Затестил линуксом. Результат: если вместо вин7 на компе запускаем линукс, то скорость отправки с 8,2 понимается до 50-55 мбайт/с. Может и до 100 поднялось бы на тесте линукс-линукс, но у меня возможен только тест линукс-виндовс. Главное что это доказывает что железо ни при чем.

Дальше интереснее. По ходу тестов обнаружил интересную багофичу вин7. sendto() может подвиснуть из-за конретного значения IP.
тест
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
#include <winsock2.h>
#include <Ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")

#include <stdio.h>
#include <stdlib.h>

void send_udp(SOCKET sock, char* msg, int size, char* addr_str, int port)
{
	sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr(addr_str);
	printf("send %d byte to %s:%d ", size, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
	int start = GetTickCount();
	int send = sendto(sock, msg, size, 0, (SOCKADDR *) &addr, sizeof(sockaddr_in));
	if(send == size) {
		printf("OK pause %d msec\n", GetTickCount() - start);
	} else {
		printf("failed %d\n", send);
	}


}

void main(int argc, char* argv[])
{
	WSADATA wsaData;
	if(WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
		printf("WSAStartup()\n");
		return;
	}

	sockaddr_in addr_in;
	addr_in.sin_family = AF_INET;
	addr_in.sin_port = htons(0);
	addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
	SOCKET sock_udp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if(bind(sock_udp, (SOCKADDR *) &addr_in, (socklen_t) sizeof(sockaddr_in)) != 0) {
		printf("bind()\n");
		return;
	}

	char msg[1472];
	send_udp(sock_udp, msg, 1472, "192.168.0.1", 57691);
	send_udp(sock_udp, msg, 1472, "169.254.160.21", 57691);

	system("pause");
}


результат на 2-х компах с Win7send 1472 byte to 192.168.0.1:57691 OK pause 0 msec
send 1472 byte to 169.254.160.21:57691 OK pause 2793 msec
оба IP не из моей подсети.

Есть третий комп, там W7 не совсем исходная, правили что-то в реестре связанное с сетью, чтобы проблем не было из XP к ней цепляться. На этом компе тест прошел по нулям и скорость UDP повыше 12-13 мбайт/с, я с него тестил отправку через инет, поэтому было 10, а не 8,2.

Не знаю связано это явление или нет с проблемой медленной скорости, но порешать как-то надо, менять настройки ОС не вариант, в идеале настройкой сокета полечить, в крайнем случае сверять локальные IP со своими на общую подсеть, прежде чем слать туда чего-либо.

Вобщем подтверждается что в винде надо настройками играться.
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894523
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,

169.254.* - это link local address. Они могут по-другому рутерами обрабатываться (даже точнее - должны).
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894525
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А еще конкретнее - они не должны маршрутизироваться между подсетями.
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894548
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyDima T,

169.254.* - это link local address. Они могут по-другому рутерами обрабатываться (даже точнее - должны).
это никак не объясняет подвисание sendto() почти на 3 секунды !!! Это ж UDP, сунул в буфер и трудись дальше, а винда пусть разбирается слать роутерам или сразу выкинуть.
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894563
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,

В доке есть такое примечание:
When issuing a blocking Winsock call such as sendto, Winsock may need to wait for a network event before the call can complete. Winsock performs an alertable wait in this situation, which can be interrupted by an asynchronous procedure call (APC) scheduled on the same thread.Возможно, наведет на какие-то мысли.
Правда, что это за network event - не знаю.
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894567
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Tподвисание sendto() почти на 3 секунды !!!Случаем, это не ожидание arp-ответа?
Что если этот адрес внести как фиксированную запись в arp-таблицу?
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894683
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoftDima Tподвисание sendto() почти на 3 секунды !!!Случаем, это не ожидание arp-ответа?
Что если этот адрес внести как фиксированную запись в arp-таблицу?
Проблема в том что я не знаю что вносить, а что нет. Работает так: отправитель и получатель, каждый открывает случайный UDP порт (в примере видно addr_in.sin_port = htons(0);) и каждый через сервер посылает все свои интерфейсы (IP:порт) второму и начинают на них слать тестовые пакеты, пришел правильный ответ - связь есть, шлем инфу. Данный адрес был от интерфейса для связи с виртуалкой на втором компе, понятно что первый комп не достучится по нему, но такой нездоровый глюк с подвисанием я не ожидал.
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894697
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoftDima T,

В доке есть такое примечание:
When issuing a blocking Winsock call such as sendto, Winsock may need to wait for a network event before the call can complete. Winsock performs an alertable wait in this situation, which can be interrupted by an asynchronous procedure call (APC) scheduled on the same thread.Возможно, наведет на какие-то мысли.
Правда, что это за network event - не знаю.
Буду читать вечером, может нарою чего.
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894715
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ты по-прежнему веришь в сказочку, что UDP производительнее TCP. Ню-ню...
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894879
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TЕсли слать через localhost, т.е. на одном компе отправитель и приемник, то получаю 800-900 мбит.
Глубина и полезность этого эксперимента поражают своим размахом.
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894881
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovТы по-прежнему веришь в сказочку, что UDP производительнее TCP. Ню-ню...
Слабенький наброс ))
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894899
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovТы по-прежнему веришь в сказочку, что UDP производительнее TCP. Ню-ню...

Мои тесты показывают что не медленнее, хотя можно оценивать результаты по разному. На коротких дистанциях одинаково. Выжал ведь все 100 мбит из 100 мбитной внутренней сетке провайдера.

ТСР не дает мне возможности соединить двух клиентов, которые в одном городе, в одном провайдере или вообще в локалке. Каждый сидит за брэндмауэром виндовса и НАТом роутера. Может в виндовсе еще дадут порт открыть, а в роутере точно никто мапить порты не будет. Остается поднять свой сервер где-нибудь и гонять через него. А где поднять? На хостинге, на виртуалке. Только хостинги ближайшие нормальные в Москве, для клиентов это 2000-4000 км по проводам, по среднему 6000 км (клиентА-сервер-клиентБ), это 20 мс со скоростью света только в один конец. Это в идеале, реально еще больше, т.к. задержки на оборудовании, т.е. 30-40 мс. Реально они максимум в сотне км друг от друга. Думаю дальше сам посчитаешь что быстрее: по TCP 6000 км или по UDP 100 км? И сообщения у меня небольшие (10-100 кб), за 20 мс даже с потерями долетят несколько раз.

С TCP все-равно придется связаться, т.к. через GSM-свистки потери гигантсткие, наверно чтобы скайп не пользовали и торрентами каналы не забивали.

В целом пока все идет нормально, осталось с засадой от виндовса разобраться.
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894903
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Tчерез GSM-свистки потери гигантсткиеПопробуйте номера портов поварьировать. По идее, например, с 53 портом такого не должно быть.
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894923
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoftDima Tчерез GSM-свистки потери гигантсткиеПопробуйте номера портов поварьировать. По идее, например, с 53 портом такого не должно быть.
Уже написал что второй абонент за роутером, там НАТ точно не даст 53 порт, выдаст какой-нибудь на свое усмотрение. Это направление вообще тупиковое, у меня нет доступа к оборудованию соединяющихся, и желания нет админить там что-то, т.к. платить за это никто не будет. Таких немного, для них проще сделать TCP до сервера, а дальше UDP.
Большинство по UDP без потерь шлют.
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894934
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Tтам НАТ точно не даст 53 портDNS-же как-то работает?
...
Рейтинг: 0 / 0
Как выжать весь гигабит по UDP?
    #38894949
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вы плохо понимаете какой фигнёй мается автор.
А DNS работает "на общих основаниях" - пакет на сервер отправляет "nat-ируемый" компьютер.
...
Рейтинг: 0 / 0
25 сообщений из 162, страница 1 из 7
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как выжать весь гигабит по UDP?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]