Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Как выжать весь гигабит по UDP? / 25 сообщений из 162, страница 1 из 7
03.03.2015, 20:38
    #38894066
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как выжать весь гигабит по UDP?
Наткнулся на странную проблему: виндовс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
03.03.2015, 20:44
    #38894075
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как выжать весь гигабит по UDP?
Dima T,

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

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

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

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

Гы, а почему проц вообще должен быть загружен? Ну да, что-то он там управляет, но нагрузка-то основаная тупо на сеть.
...
Рейтинг: 0 / 0
04.03.2015, 13:13
    #38894512
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как выжать весь гигабит по UDP?
Затестил линуксом. Результат: если вместо вин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
04.03.2015, 13:21
    #38894523
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как выжать весь гигабит по UDP?
Dima T,

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

169.254.* - это link local address. Они могут по-другому рутерами обрабатываться (даже точнее - должны).
это никак не объясняет подвисание sendto() почти на 3 секунды !!! Это ж UDP, сунул в буфер и трудись дальше, а винда пусть разбирается слать роутерам или сразу выкинуть.
...
Рейтинг: 0 / 0
04.03.2015, 13:51
    #38894563
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как выжать весь гигабит по UDP?
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
04.03.2015, 13:52
    #38894567
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как выжать весь гигабит по UDP?
Dima Tподвисание sendto() почти на 3 секунды !!!Случаем, это не ожидание arp-ответа?
Что если этот адрес внести как фиксированную запись в arp-таблицу?
...
Рейтинг: 0 / 0
04.03.2015, 14:55
    #38894683
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как выжать весь гигабит по UDP?
miksoftDima Tподвисание sendto() почти на 3 секунды !!!Случаем, это не ожидание arp-ответа?
Что если этот адрес внести как фиксированную запись в arp-таблицу?
Проблема в том что я не знаю что вносить, а что нет. Работает так: отправитель и получатель, каждый открывает случайный UDP порт (в примере видно addr_in.sin_port = htons(0);) и каждый через сервер посылает все свои интерфейсы (IP:порт) второму и начинают на них слать тестовые пакеты, пришел правильный ответ - связь есть, шлем инфу. Данный адрес был от интерфейса для связи с виртуалкой на втором компе, понятно что первый комп не достучится по нему, но такой нездоровый глюк с подвисанием я не ожидал.
...
Рейтинг: 0 / 0
04.03.2015, 15:02
    #38894697
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как выжать весь гигабит по UDP?
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
04.03.2015, 15:10
    #38894715
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как выжать весь гигабит по UDP?
Ты по-прежнему веришь в сказочку, что UDP производительнее TCP. Ню-ню...
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
04.03.2015, 17:17
    #38894879
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как выжать весь гигабит по UDP?
Dima TЕсли слать через localhost, т.е. на одном компе отправитель и приемник, то получаю 800-900 мбит.
Глубина и полезность этого эксперимента поражают своим размахом.
...
Рейтинг: 0 / 0
04.03.2015, 17:17
    #38894881
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как выжать весь гигабит по UDP?
Dimitry SibiryakovТы по-прежнему веришь в сказочку, что UDP производительнее TCP. Ню-ню...
Слабенький наброс ))
...
Рейтинг: 0 / 0
04.03.2015, 17:26
    #38894899
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как выжать весь гигабит по UDP?
Dimitry SibiryakovТы по-прежнему веришь в сказочку, что UDP производительнее TCP. Ню-ню...

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

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

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

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


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