Перегрузка TCP высокочастотного прослушивателя данных в Windows 7 - PullRequest
1 голос
/ 20 декабря 2011

Я кодировал слушатель на основе ac # для извлечения данных с сервера фондового рынка.Проблема заключается в том, что после мониторинга через WireShark окно TCP заполняется, что означает, что принимающему хосту (мне) не удается обработать входящие данные достаточно быстро.

Я знаю, что мой провайдер данных отключил подтверждение TCP со своей стороны, поэтому он просто отправляет пакеты TCP и проверяет, все ли они еще там: если он обнаруживает, что они не были обработаны через определенное время, соединение просто отключено.

Я действительно не знаю, что делать, я отключил автоматическую настройку масштаба Windows 7, а также эвристику, но это не имело никакого эффекта.Я также заметил, что нет способа установить размер Windows TPC (RWIN) в Windows 7.

Я знаю, что это не вопрос, связанный с программированием per se , но так или иначе, потому что этокритично с точки зрения кода.

РЕДАКТИРОВАТЬ
Ответчик заявил: «Ваше приложение недостаточно быстро извлекает данные из него». Это довольно интересно, но у меня естьнет реальной идеи о том, как оптимизировать это:

    private class IoContext
    {
        // The socket used for the operation:
        public Socket _ipcSocket;
        // The buffer used for the operation:
        public VfxMsgBlock _ipcBuffer;

        public IoContext(Socket socket, VfxMsgBlock buffer)
        {
            _ipcSocket = socket;
            _ipcBuffer = buffer;
        }
    }

    private void InitiateRecv(IoContext rxContext)
    {
        rxContext._ipcSocket.BeginReceive(rxContext._ipcBuffer.Buffer, rxContext._ipcBuffer.WrIndex,
            rxContext._ipcBuffer.Remaining(), 0, CompleteRecv, rxContext);
    }

    private void CompleteRecv(IAsyncResult ar)
    {
        IoContext rxContext = ar.AsyncState as IoContext;
        if (rxContext != null)
        {
                int rxBytes = rxContext._ipcSocket.EndReceive(ar);
                if (rxBytes > 0)
                {
                    //Adjust the write index in the message block:
                    rxContext._ipcBuffer.WrIndex = rxContext._ipcBuffer.WrIndex + rxBytes;

                    //(...) Do Stuf here with data                        

                    rxContext._ipcBuffer.Crunch();

                    //Initiate another asynchronous read:
                    InitiateRecv(rxContext);
                }                
          }
     }

РЕДАКТИРОВАТЬ 2
В ответ на Лена Холгейта:

Я изменил / проверил размер буфера Recv напрямуючерез свойство c # (возникли некоторые проблемы при использовании GetSocketOption / SetSocketOption)

Я могу заметить небольшое изменение производительности, когда я изменяю размер Socket Buffer, т. е. соединение падает после 10 мин с большим буфером (1000000), а не 3 мин (используя10240 или меньше (даже 0, я не знаю, почему ... странно))

Вот первый журнал WireShark, который я получаю:

[SYN, ACK] Seq=0 Ack=1 Win=5840 Len=0 MSS=1380 SACK_PERM=1 WS=128

Это ничего не меняетРазмер принимающего буфера сокета

Что касается Windows 7 и TCP Размер Windows, я имел в виду, что перезапись TCP Management в Windows привела к тому, что он масштабировался автоматически, и нет параметра реестра, который можно было бы установить «вручную».
Однако вы правы: для каждого сокета это настраивается с использованием размера буфера приема.
Источник здесь среди прочих

Ответы [ 3 ]

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

Вы установили максимальный размер буфера recv сокета?

См. Здесь, как повлиять на размер окна TCP: http://msdn.microsoft.com/en-us/library/ms819736.aspx

Отредактировано , чтобы показать, что я получаю с двумя машинами win 7 по ссылке 1 ГБ, без измененийк настройкам по умолчанию, просто установите SO_RECVBUF с помощью setsockopt() на сокете прослушивания, размер окна проверен из журнала подключения Wireshark ... Фактический размер окна рассчитывается из объявленного размера и множителя, который подразумевается при масштабированиифактор.

 Set Recv  |Advertised |Scaling|Multiply| Actual TCP |Difference|
   Buf to  |  Window   |       |  By    |Window size |          |
   --------+-----------+-------+--------+----------- +----------+
   default |   8192    |   8   |    256 |    2097152 |          | 
      1024 |   1024    |   0   |      1 |       1024 |         0|
     10240 |  10240    |   0   |      1 |      10240 |         0|
  66666666 |  65535    |  10   |   1024 |   67107840 |   -441174|
 666666666 |  65535    |  14   |  16384 | 1073725440 |-407058774|
1000000000 |  65535    |  14   |  16384 | 1073725440 | -73725440|
1073725440 |  65535    |  14   |  16384 | 1073725440 |         0|
1073741823 |  65535    |  14   |  16384 | 1073725440 |     16383|
1073741824 |   8192    |   8   |    256 |    2097152 |1071644672|
2147483647 |   8192    |   8   |    256 |    2097152 |2145386495|

Таким образом, очевидно, что в Windows 7 можно влиять на размер окна TCP для каждого сокета отдельно. Не могли бы вы предоставить ссылку на документ, который делает васПолагайте, что "Начиная с Windows 7, я только что сказал, что больше нет размера окна TCP, доступного для ручной настройки (только для опции автонастройки netsh)" , пожалуйста.

Обратите внимание, что параметр recv buf должен быть применен к прослушивающему сокету или исходящему сокету до того, как вы выполните соединение, так как масштабирование размера окна передается при открытии рукопожатия.

Во всех случаях вызов setsockopt() был успешным, и немедленный вызов getsockopt() сообщил, что размер буфера записи равен размеру, который был запрошен при предыдущем вызове setsockopt().

Обратите внимание, что хотя теоретическим максимумом является максимальное значение беззнакового целого, 2147483647, фактическое максимальное полезное значение представляется равным 1073741823 (0x3FFFFFFF), но оно может варьироваться в зависимости от версии операционной системы, но имейте в виду, что немедленный вызов getsockopt() вернулто же значение, которое было установлено, поэтому было невозможно, кроме как путем просмотра журнала wireshark, определить, что значения выше 1073741823 были полностью проигнорированы (по крайней мере, с точки зрения размера окна).

Конечно, это требует, чтобыподключающийся узел задает параметр масштабирования окна, даже 0, чтобы показать, что он принимает масштабирование окна.

Пожалуйста, покажите нам журнал подключений wireshark для начальных пакетов рукопожатия.Я могу предоставить скомпилированный код, чтобы вы могли проверить это, если хотите.

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

Если вы отключите обработку ACK в TCP, вы больше не будете разговаривать по TCP. Вы используете какой-то странный frankenprotocol, который немного похож на TCP.

Как правило, хотя вы должны использовать автоматическую настройку Windows TCP - это довольно хорошо, хотя это зависит от того, кто говорит по TCP (что в вашем случае не так).

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

Наконец, если вы хотите использовать UDP, вам, вероятно, следует попробовать использовать UDP вместо wierd TCP.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...