Как ускорить медленную / запаздывающую передачу Windows Socket 7 (WP7) TCP Socket - PullRequest
7 голосов
/ 24 декабря 2011

Недавно я начал использовать класс System.Net.Sockets, представленный в выпуске WP7 для Mango, и в целом наслаждался им, но заметил несоответствие между задержкой передачи данных в режиме отладки и обычной работой по телефону..

Я пишу приложение "удаленное управление", которое передает один байт на локальный сервер в моей локальной сети через Wi-Fi, когда пользователь нажимает кнопку в приложении.Следовательно, воспринимаемая отзывчивость / своевременность приложения очень важна для хорошего пользовательского опыта.

Когда телефон подключен к моему ПК через USB-кабель и работает приложение в режиме отладки, TCP-соединение, кажется, передает пакетытак же быстро, как пользователь нажимает кнопки.

Когда телефон отключен от ПК, пользователь может нажать до 7 кнопок (и, таким образом, в случае 7 команд «отправить» с 1-байтовыми полезными нагрузками, прежде чем будут отправлены все 7 байтов).) Если пользователь нажимает кнопку и немного ждет между нажатиями, кажется, что задержка составляет 1 секунду.

Я пытался установить для Socket.NoDelay значения True и False, и кажется,без разницы.

Чтобы увидеть, что происходит, я использовал анализатор пакетов, чтобы посмотреть, как выглядит трафик.

  • Когда телефон был подключен через USB к ПК (который использовал соединение Wi-Fi), каждый отдельный байт находился в своем собственном пакете с интервалом ~ 200 мс.

  • Когда телефон работал по собственному Wi-Fi-соединению (отключенному от USB), байты все еще имели свои собственные пакеты, но все они были сгруппированы в пакеты по 4 или 5 пакетов икаждая группа находилась на расстоянии ~ 1000 мсек друг от друга.

btw, время пинга в моей сети Wi-Fi до сервера составляет всего 2 мс по сравнению с моим ноутбуком.

IПонимаете, что буферизация «отправляет» вместе, вероятно, позволяет телефону экономить энергию, но есть ли способ отключить эту «задержку»? Отзывчивость приложения важнее, чем экономия энергии.

Ответы [ 6 ]

2 голосов
/ 02 января 2012

Эндрю Бернетт-Томпсон здесь уже упоминал об этом, но он также написал, что это не сработало для вас. Я не понимаю и не вижу ПОЧЕМУ. Итак, позвольте мне объяснить эту проблему:

Алгоритм Nagle был введен, чтобы избежать сценария, когда много небольших пакетов должны были быть отправлены через сеть TCP. Любой текущий современный стек TCP включает алгоритм Nagle по умолчанию!

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

Лучшее объяснение алгоритма Нэгла и его фона можно найти в Википедии .

Итак, ваша первая попытка: отключить алгоритм Nagle для вашего TCP-соединения, установив опцию TCP_NODELAY в сокете. Это уже решило вашу проблему? Ты вообще видишь разницу?

Если не так, тогда дайте мне знак, и мы углубимся в детали.

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

2 голосов
/ 29 декабря 2011

Это действительно интересный вопрос!Я собираюсь бросить свои 2 цента, но, пожалуйста, имейте в виду, я не эксперт по System.Net.Sockets на WP7.

Во-первых, тестирование производительности в отладчике следует игнорировать.Причина этого заключается в том, что дополнительные издержки на запись трассировки стека всегда замедляют работу приложений, независимо от ОС / языка / IDE.Приложения должны быть профилированы для производительности в режиме выпуска и отключены от отладчика.В вашем случае это на самом деле медленнее отключен!Итак, давайте попробуем оптимизировать это.

Если вы подозреваете, что пакеты буферизуются (и это разумное предположение), вы пытались отправить пакет большего размера?Попробуйте линейно увеличить размер пакета и измерить задержку.Не могли бы вы написать на устройстве простой микро-профилировщик в коде , т. Е. Использовать класс DateTime.Now или секундомер для регистрации задержки по сравнению с размером пакета.Построение графика может дать вам хорошее представление о том, верна ли ваша теория.Если вы обнаружите, что 10-байтовые (или даже 100-байтовые) пакеты отправляются мгновенно, я бы посоветовал просто передавать больше данных за одну передачу.Я знаю, что это глупый хак, но если он не сломался ...

Наконец, вы говорите, что используете TCP.Можете ли вы попробовать UDP вместо этого?TCP предназначен не для связи в реальном времени, а для точной связи.UDP, напротив, не проверяется на ошибки, вы не можете гарантировать доставку, но вы можете ожидать от него более быстрой (более легкой, меньшей задержки) производительности.Сети, такие как Skype и онлайн-игры, построены на UDP, а не на TCP.Если вам действительно нужно подтверждение получения, вы всегда можете создать свой собственный микропротокольный протокол по UDP, используя собственную проверку циклическим избыточным кодом для проверки ошибок и протокол запроса / ответа (подтверждения) .

Такие протоколы существуют, взгляните на Надежный UDP , обсуждаемый в этого предыдущего вопроса .Существует реализация RUDP на основе Java, но я уверен, что некоторые части могут быть перенесены в C #.Конечно, первый шаг - проверить, действительно ли UDP помогает!


Нашел этот предыдущий вопрос, в котором обсуждается проблема.Возможно, проблема с Wp7? Низкая производительность UDP с Windows Phone 7.1 (Mango)

Тем не менее, было бы интересно узнать, работает ли увеличение размера пакета или переключение на UDP


нормально, так что никаких предложенийработал.Я нашел это описание алгоритма Nagle, который группирует пакеты, как вы описываете.Настройка NoDelay должна помочь, но, как вы говорите, не помогает.

http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.nodelay.aspx

Также.Посмотрите этот предыдущий вопрос, где Keepalive и NoDelay были включены / выключены для ручной очистки очереди.Его свидетельство анекдотично, но стоит попробовать.Можете ли вы попробовать и отредактировать свой вопрос, чтобы публиковать более свежие результаты?

Сокет "Flush", временно включив NoDelay

1 голос
/ 02 января 2012

Вы пробовали установить SendBufferSize = 0? В 'C' вы можете отключить буферизацию winsock, установив SO_SNDBUF в 0, и я предполагаю, что SendBufferSize означает то же самое в C #

1 голос
/ 30 декабря 2011

Похоже, что ваши чтения / записи буферизируются. Вы можете попробовать установить для свойства NoDelay в Socket значение true, вы также можете обрезать размеры буфера отправки и получения. Снижение скорости отклика может быть побочным продуктом нехватки трафика WiFi, я не уверен, что настройка MTU является опцией, но уменьшение MTU может улучшить время отклика.

Все это только варианты для решения с низкой пропускной способностью, если вы собираетесь перекладывать мегабайты данных в любом направлении, вам понадобятся большие буферы по Wi-Fi, достаточно большие, чтобы компенсировать задержку передачи, обычно в диапазоне 32K- 256K.

    var socket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
    {
        NoDelay = true,
        SendBufferSize = 3,
        ReceiveBufferSize = 3,                
    };

Я не проверял это, но вы поняли.

1 голос
/ 24 декабря 2011

Скорее всего, это не проблема программного обеспечения.Если телефон использует WiFi, задержка может быть выше 70 мс (в зависимости от того, где находится сервер, какая у него пропускная способность, насколько он занят, помехи для точки доступа и расстояния от точки доступа), но большая часть задержкиэто просто WiFi.Использование GMS, CDMA, LTE или любой другой технологии, используемой телефоном для передачи данных, еще медленнее.Я бы не подумал, что вы получите намного меньше, чем 110 мс на сотовом устройстве, если не будете стоять под вышкой сотовой связи.

0 голосов
/ 07 января 2013

Вы случайно использовали Lumia 610 и точку доступа mikrotik?

У меня возникла эта проблема, она заставила Lumia 610 отключить радио Wi-Fi, как только было закрыто последнее соединение.Эта добавленная ощутимая задержка, по сравнению с Lumia 800, например.Все соединения были затронуты - простое отключение Wi-Fi сделало все приложения быстрее.Мой админ говорит, что в то время микротикс не поддерживал некоторые функции в сочетании с настройками WMM.Как ни странно, с большинством других телефонов все было в порядке, поэтому вначале мы обвиняли в дешевизне 610.

Если вы все еще можете повторить проблему, я предлагаю попробовать следующее:другое соединение в фоновом режиме и пинговать его все время.

использовать 3g / gprs вместо wifi (требуется подключение вашего сервера к Интернету) использовать другой (или обновленный) телефон использовать другой (или обновленный) AP
...