【问题标题】:Tcl: Understanding IO channelsTcl:了解 IO 通道
【发布时间】:2021-09-07 04:34:24
【问题描述】:

在浏览下面链接中的答案时,我了解到“open”命令打开了一个 IO 通道进行读/写,类似于 socket 命令的作用。

链接:How can I redirect stdout into a file in tcl

问题:看起来一旦您使用close stdout 关闭标准输出,默认通道就会移动到使用open $file w 创建的内容。为什么这在套接字 IO 编程中不起作用。例如:

set sock [socket -server $port]

close stdout

puts "hello there"

错误:找不到名为“stdout”的频道

期待puts命令的输出直接进入频道

【问题讨论】:

  • 您必须先关闭标准输出,然后下一个打开的描述符将替换它。有关逻辑,请参见 stackoverflow.com/a/68869664/9952196,只需将描述符 0 替换为 1。
  • 尝试颠倒命令的顺序。首先close stdout 然后set sock [socket -server $port] 我得到这个错误“通道“stdout”没有打开写入”。它可能期望标准输出可用作可写通道
  • 你必须使用一个连接的套接字,而不是仅仅监听连接。
  • 您缺少socket -server 的参数,顺便说一句。
  • 是的,套接字已连接到客户端。客户端执行socket $host $port 并连接到服务器,我可以正确地在服务器端放置。你是这个意思吗?对,完整的命令是set sock [socket -server Accept $port]。

标签: sockets tcl stdout


【解决方案1】:

首先,socket -server 是它自己的特殊事物。当客户端连接时,它必然会进行回调(accept() 系统调用的底层基础结构对您隐藏)。使用服务器套接字也不能做太多其他事情。特别是,您无法在服务器套接字上读取或写入,因为没有连接另一端。

创建的连接套接字(实际上只是普通的客户端套接字,除了它们是如何制作的)正在使用操作系统分配的任何文件描述符; Tcl 不会重新分配它们。 强烈建议您不要尝试在任何标准通道上接受接受,但 POSIX 支持通过重定向将连接的套接字传递给子进程(我不知道它是否适用视窗)。你会这样做:

socket -server spawnSubprocess 12345

proc spawnSubprocess {sock host port} {
    puts "connection from ${host}:${port}"
    exec [info nameofexecutable] myscript.tcl <@$sock >@$sock 2>@$sock &
    # You might want stderr to not go back to the client...
    close $sock
}

vwait forever

请注意,子进程可以使用fconfigure 发现套接字配置。

一般来说,虽然可以重定向标准频道,但实际执行时会非常混乱。最好让他们连接到呼叫过程告诉他们去的任何地方。但是为您创建的子流程重定向绝对没问题。

【讨论】:

  • 另请注意,上述代码容易受到 DDoS 攻击,因为它创建子进程的速度与接收连接的速度一样快。强烈建议在生产环境中使用防火墙。
  • 感谢@donal-fellows。我注意到当我在客户端运行close stdout 然后连接到服务器时。我可以通过客户端上的 puts 成功打印服务器上的任何内容,这类似于按照您的示例关闭标准输出并打开文件。为什么我不能运行类似 close stdout; socket -server ... 的东西;连接客户端,然后在服务器上放置并在客户端上打印回来? (因为它适用于客户端)
猜你喜欢
  • 2016-03-17
  • 1970-01-01
  • 2018-08-27
  • 2020-01-05
  • 2018-02-02
  • 2019-05-10
  • 1970-01-01
  • 1970-01-01
  • 2022-01-14
相关资源
最近更新 更多