fileevent в TCL очень медленный - PullRequest
       14

fileevent в TCL очень медленный

0 голосов
/ 15 октября 2018

Я пытался написать код в TCL.Идея состоит в том, чтобы написать код, который выполняет прокси через Cisco.Мой cisco - это версия 12.4 cisco 3700, а версия TCL - 8.3.Я работаю с GNS (Graphical Network Simulator), поэтому все компоненты являются виртуальными (включая cisco).

В своем коде я открыл 2 сокета с двумя разными компьютерами: sock1 и sock2.Я настроил эти сокеты следующим образом:

fconfigure $sock1 -translation binary -buffering none -blocking 0
fconfigure $sock2 -translation binary -buffering none -blocking 0

Теперь я попытался передать информацию между ними (прокси).Пока я читаю, язык однопоточный, и поэтому мне нужно использовать события.Итак, я создал два обработчика событий файла, которые вызвали функцию:

fileevent $sock1 readable [list proxy $sock1 $sock2]
fileevent $sock2 readable [list proxy $sock2 $sock1]

Прокси-функция считывает данные из первого сокета и отправляет их в другой сокет.

Код работает хорошо:Я перевёл rdp и smb по этому прокси.Проблема в том, что это действительно медленно: это занимает что-то вроде 1000-1100 мс.Поэтому я не могу использовать удаленный рабочий стол через прокси, и даже smbclient работает очень медленно.Функция прокси очень быстрая (я проверил ее, а также попытался распечатать в начале и в конце функции).Поэтому я предполагаю, что прерывания от ОС очень медленные (или tcl медленно выполняет скрипт).Кроме того, я открыл wireshark по обе стороны от cisco, и между входящим и исходящим сообщениями проходит секунда.

Другая информация:

Я хочу, чтобы некоторые клиенты одновременно общалисьпоэтому мой код TCL определяет сокет сервера:

set server_socket [socket -server handle_conn $port]
vwait is_finish

, а функция handle_conn открывает сокет на второй стороне и создает обработчики событий файла:

proc handle_conn{sock1 addr port} {
    CREATE THE SECOND SOCKET (sock2)
    fileevent $sock1 readable [list proxy $sock1 $sock2]
    fileevent $sock2 readable [list proxy $sock2 $sock1]
}

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

Я не могу понять, связана ли проблема с fconfigure, с событиями в tcl, с gns или с другой проблемой.Надеюсь на помощь!

Редактировать:

proc proxy {s1 s2} {
if {([eof $s1] || [eof $s2]) || ([catch {read $s1} data] || [catch {puts -nonewline $s2 $data}])} {
    catch {close $s1}
    catch {close $s2}
}

1 Ответ

0 голосов
/ 15 октября 2018

Мне любопытно, что код медленный для вас;Tcl достаточно быстр, чтобы использовать его для реализации полнофункциональных веб-серверов, обрабатывающих сложный контент.Это заставляет меня подозревать, что происходит что-то еще.Например, команда proxy звучит так, как будто она в основном просто копирует байты из одного канала в другой, но есть медленные способы сделать это и есть быстрые способы.Один из лучших способов - перевести оба канала в двоичный режим (fconfigure $chan -translation binary), а затем использовать fcopy в асинхронном режиме для перемещения байтов;он был внутренне оптимизирован для использования эффективных размеров буфера и ограничения количества копий между буферами памяти.Вот как может выглядеть команда proxy:

proc proxy {sourceChannel destinationChannel} {
    fconfigure $sourceChannel -translation binary
    fconfigure $destinationChannel -translation binary
    fcopy $sourceChannel $destinationChannel -command [list \
            copydone $sourceChannel $destinationChannel]
}

Процедура copydone вызывается, когда все перемещается.Вот базовый пример, но вам, возможно, нужно быть немного более осторожным, поскольку у вас есть копии, идущие в обоих направлениях:

proc copydone {src dst numBytes {errorMsg ""}} {
    # $numBytes bytes of data were moved
    close $src
    close $dst
    if {$error != ""} {
        puts stderr "error in fcopy: $error"
    }
}

Если бы не тот факт, что вы работаете в ciscoЯ бы также предложил обновить используемую версию Tcl.Формально 8.3 долгое время не поддерживалось.

...