Определение скорости существующего TCP соединения
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.217.9] |
|
|
Соблюдайте общие правила форума
MSDN Library
FAQ раздела
Поиск по разделу
Как правильно задавать вопросы
Определение скорости существующего TCP соединения
|
Сообщ.
#1
,
|
|
|
|
Приветствую всех зашедших!
Есть небольшая проблема, которую можно было бы решить коряво, но не хочется. С сокетами работаю по мере необходимости, считайте, что нуб. Есть приложение, состоящее из клиента и сервера (написаны на дельфи 2010, должны работать от XP и выше), которые устанавливают между собой TCP соединение используя с обоих сторон iocp (по мотиву этой статьи http://habrahabr.ru/post/145140/) Сейчас встала задача определить скорость передачи данных по уже установленному каналу, чтобы в дальнейшем по разному сжимать данные. Нужно определить как входящую, так и исходящую скорости. Протокол если что можно расширить, рандомные тестовые данные тоже можно прогнать. На GetIfTable просьба не указывать, так как там видна скорость всего интерфейса. У Александра есть интересный пример , который использует устаревшие функции AllocateAndGetTcpExTableFromStack и AllocateAndGetUdpExTableFromStack. Я так понимаю, что сейчас нужно использовать GetExtendedTcpTable, но она не дает информации о размере трафика, прошедшего по соединению. Ну и ладно. Теоретически можно было бы как-нибудь синхронизировать время клиента и сервера, отправить сколько-то тестовых данных и посмотреть за сколько они придут. Но это помоему тоже какое-то крайнее решение. Думал замерить как-то работу WSASend, но как и надо думать - вызов асинхронный, мерить нечего. Причем этот вызов легко проглатывает буферы в 5мб Тут я решил подумать, что если я отправляю 1гб, ведь он же не выплевывается весь в сеть, а, насколько я помню, им заполняются небольшие tcp-окна, и пока не придет подтверждение доставки окна, его куски будут отправляться снова и снова. Даже если создать еще одно соединение на блокируемых сокетах, будет ли гарантия, что время вызова send-а и есть время посылки или это время копирования данных в буфер какого-то уровня tcp-стека? В общем как лучше измерить время отправки данных? Может быть стоит как-то довести буфер сокета до переполнения (ведь должна же вернуться ошибка при какой-то огромной передаче?) и периодически досылать туда данные и смотреть сколько влезет и за какое время? PS: Время скачивания можно получить путем замера сервером времени передачи и оповещения о результате клиента. |
|
Сообщ.
#2
,
|
|
|
|
Цитата SerSEr @ им заполняются небольшие tcp-окна, и пока не придет подтверждение доставки окна, его куски будут отправляться снова и снова. Емнип, макс. размер окна 65кило, кроме того у него переменный размер, также не стоит забывать про сongestion сontrol. Добавлено Я делал скоростомер целиком интерфейса, разницей между двумя соседними значениями полученных/отправленных байт. Это единственный метод который я знаю. Все остальное, имхо, нереал. Цитата Может быть стоит как-то довести буфер сокета до переполнения (ведь должна же вернуться ошибка при какой-то огромной передаче?) Насколько я знаю, флагами tcp ты управлять не могешь, соот-но выставить DF=1 тоже, значит и переполнить не получится, имхо. |
|
Сообщ.
#3
,
|
|
|
|
Цитата Насколько я знаю, флагами tcp ты управлять не могешь, соот-но выставить DF=1 тоже, значит и переполнить не получится, имхо. Я имел ввиду, что можно переполнять виндовский буфер, который по мере отправки должен потихоньку освобождаться, а как там будут фрагментироваться пакеты в принципе неважно. Про сongestion сontrol тоже думаю не стоит заморачиваться, потому что затор это более менее нормальная ситуация, можно просто померить несколько раз с каким-то промежутком. Цитата Я делал скоростомер целиком интерфейса, разницей между двумя соседними значениями полученных/отправленных байт. Это единственный метод который я знаю. Все остальное, имхо, нереал. Для этого ты просто загружал соединение какой-то скачкой/закачкой? Еще, конечно, хорошо было бы не гнать излишний трафик. Ведь предположим: 1. Сервер посылает клиенту команду начала теста скорости (все остальные задачи в рамках этого соединения приостанавливаются) 2. Сервер начинает гнать в сокет 10мб 3. Клиент получает сообщение начала и начинает принимать данные, замеряя скорость. 4. Скорость клиента может быть как 4мб/с (выделенка), так и 20кб/с (модем, телефон, итд) 5. Клиент за минуту принимает 1мб, уже более менее достоверно определяя свою скорость 6. На сервере в это время где-то в буфере винды остается еще 9мб (!), которые полюбому отправятся и которые клиент должен будет принимать еще ~9 минут. Вот как избавиться от последнего пункта? |
|
Сообщ.
#4
,
|
|
|
|
Разрывать соединение по таймеру?
|
|
Сообщ.
#5
,
|
|
|
|
Тоже конечно вариант, но уж очень не вписывается в остальную логику
|
|
Сообщ.
#6
,
|
|
|
|
Цитата SerSEr @ 6. На сервере в это время где-то в буфере винды остается еще 9мб (!), которые полюбому отправятся и которые клиент должен будет принимать еще ~9 минут. Если клиент оборвет коннект после одной минуты, то send вернёт <= 0, что и будет сигналом завершить прогон данных. А по сути вопроса, кмк, ничего лучше прогона инфы в единицу времени не придумать, все эти "спецфункции" - черный ящик. Добавлено Цитата SerSEr @ Даже если создать еще одно соединение на блокируемых сокетах, будет ли гарантия, что время вызова send-а и есть время посылки или это время копирования данных в буфер какого-то уровня tcp-стека? Время копирования в буфер незначительно, на то он и буфер. А экспериментировать действительно легче на блокирующих. |
|
Сообщ.
#7
,
|
|
|
|
В общем все ясно. Спасибо всем за ответы
|