每个连接一个解释器/线程?(One interpreter/thread per connectio

2019-09-29 11:41发布

我想写一个服务器里的人登录,发送/输入一些命令和注销。 许多人可以在同一时间进行连接,但我不希望有很多关于每个人的状态变量,如“正在发送姓名”,“正在发送密码”,“是在上载命令的第二阶段” ......这将运行该脚本为每个传入连接的一个调用变得更为简单。

puts -nonewline $out "login: "
gets $in login ;# check for EOF
puts -nonewline $out "password: "
gets $in password ;# check for EOF
while {[gets $in command] >= 0} {
  switch -- $command {
    ...
  }
}

将内存和速度是与创建每个连接一个解释OK,即使有大约50连接? 或者,这是你可以用线程做什么?

Answer 1:

实验(观察与系统工具的交互会话)的一点点指示的Tcl应用程序中的每个Tcl解释,没有额外的用户命令,占用300KB和350KB之间的某处。 用户命令和脚本是最重要的是额外的,因为是堆栈帧(需要运行在解释什么)。 乘起来,你会得到50个解释上下文,其中任何现代计算机将处理没有慢半拍,也许17MB。 你要知道,口译不允许同时执行。

线程是重量较重,如Tcl的线程模型每个线程有自己的主解释(实际上所有解释都严格绑定到单个线程,用于大大减少全球的锁,Tcl的实现量的技术)。 正因为如此,线程数建议值将大量依赖于可用的CPU在部署硬件的数量和程度,你的代码是CPU密集型而不是IO约束。


如果您可以使用Tcl的8.6(8.6.0被标记为发布在资源库中,因为我写这篇文章,但不发货),那么你可以使用协同程序的连接状态进行建模。 他们比一个解释重量得多,可以用来做一种协作多任务处理的:

# Your code, with [co_gets] (defined below) instead of [gets]
proc interaction_body {in out} {
    try {
        puts -nonewline $out "login: "
        co_gets $in login ;# check for EOF
        puts -nonewline $out "password: "
        co_gets $in password ;# check for EOF
        if {![check_login $login $password]} {
            # Login failed; go away...
            return
        }
        while {[co_gets $in command] >= 0} {
          switch -- $command {
            ...
          }
        }
    } finally {
        close $in
    }
}

# A coroutine-aware [gets] equivalent. Doesn't handle the full [gets] syntax
# because I'm lazy and only wrote the critical bits.
proc co_gets {channel varName} {
    upvar 1 $varName var
    fileevent $channel readable [info coroutine]
    while 1 {
        set n [gets $channel var]
        if {$n >= 0 || ![fblocked $channel]} {
            fileevent $channel readable {}
            return $n
        }
        yield
    }
}
# Create the coroutine wrapper and set up the channels
proc interaction {sock addr port} {
    # Log connection by ${addr}:${port} here?
    fconfigure $sock -blocking 0 -buffering none
    coroutine interaction_$sock interaction_body $sock $sock
}

# Usual tricks for running a server in Tcl
socket -server interaction 12345;  # Hey, that port has the same number as my luggage!
vwait forever

如果你需要做的CPU密集型处理,你需要小心保护登录(可以考虑使用这种方法不适合TLS包 ,以确保使用SSL连接)。



文章来源: One interpreter/thread per connection?
标签: tcl