Asynchronous TCL中的fileevent非常慢

Asynchronous TCL中的fileevent非常慢,asynchronous,tcl,cisco,Asynchronous,Tcl,Cisco,我试着用TCL编写代码。其想法是编写代码,在cisco上执行代理。我的cisco是cisco 3700 12.4版,TCL是8.3版。我使用GNS(图形网络模拟器),因此所有组件都是虚拟的(包括cisco) 在我的代码中,我用两台不同的计算机打开了两个套接字:sock1和sock2。 我以以下方式配置了这些套接字: fconfigure $sock1 -translation binary -buffering none -blocking 0 fconfigure $sock2 -transl

我试着用TCL编写代码。其想法是编写代码,在cisco上执行代理。我的cisco是cisco 3700 12.4版,TCL是8.3版。我使用GNS(图形网络模拟器),因此所有组件都是虚拟的(包括cisco)

在我的代码中,我用两台不同的计算机打开了两个套接字: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执行脚本的速度很慢)。此外,我在cisco的两侧打开了wireshark,传入消息和传出消息之间需要秒

其他信息:

我希望一些客户端同时通信,因此我的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还是其他问题。 希望得到帮助

编辑:


我觉得奇怪的是代码对你来说太慢了;Tcl的速度足以实现处理复杂内容的完整web服务器。这让我怀疑还有别的事情在发生。例如,
proxy
命令听起来似乎主要是将字节从一个通道复制到另一个通道,但有慢的方法,也有快的方法。最好的方法之一是将两个通道置于二进制模式(
fconfigure$chan-translation binary
),然后在异步模式下使用
fcopy
移动字节;它经过内部优化,可以使用有效的缓冲区大小并限制内存缓冲区之间的复制量。以下是
代理
命令的外观:

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已经很长时间不受支持了。

您可以显示
代理的代码吗?而且Tcl 8.3非常古老。欢迎使用。我假设您已经消化了Tcler关于(双向)端口和协议转发的各种Wiki页面,例如:。您的
代理
与Wiki页面上的
中继
相比如何?旁白:您是如何处理从那时(2011年)开始强加给Cisco嵌入式TCL的(
文件事件
)的?Calvin先生,代理中的我的代码与该代码非常相似!唯一的区别是我将数据从套接字读取到变量,然后发送它@我在我的帖子中添加了代理函数的代码。不应该
proxy
停用(在调用
fcopy
之前)和
copydone
重新激活注册的
fileevent
s吗?
proc copydone {src dst numBytes {errorMsg ""}} {
    # $numBytes bytes of data were moved
    close $src
    close $dst
    if {$error != ""} {
        puts stderr "error in fcopy: $error"
    }
}