【发布时间】:2020-12-24 08:22:05
【问题描述】:
我已经创建了一个套接字客户端来连接到 python 服务器。
我检查了tcl 手动脚本,它说 "gets" - 将队列排到 EOL 字符。
手册:https://www.tcl.tk/man/tcl8.4/TclCmd/gets.htm
但是,从python服务器发送的消息是没有EOL的。
是否可以直接从缓冲区中获取?
【问题讨论】:
我已经创建了一个套接字客户端来连接到 python 服务器。
我检查了tcl 手动脚本,它说 "gets" - 将队列排到 EOL 字符。
手册:https://www.tcl.tk/man/tcl8.4/TclCmd/gets.htm
但是,从python服务器发送的消息是没有EOL的。
是否可以直接从缓冲区中获取?
【问题讨论】:
网络连接的行尾标准是 CRLF,Tcl 默认打开套接字,但服务器可能不遵循。
尝试fconfigure $mysocket -translation auto 接受 CR、LF 和 CRLF。
【讨论】:
在处理二进制数据(即不是基于行)时,read 命令通常比gets 更合适。
read 命令的手册页可在此处找到:http://www.tcl.tk/man/tcl/TclCmd/read.htm
我还鼓励您使用比已有十多年历史的 8.4 更新的 Tcl 版本。当前版本是 Tcl 8.6。
在 cmets 中提供更多详细信息后更新:
如果服务器没有指明它发送的数据的长度,没有在末尾发送换行符,也没有关闭套接字,这对客户端来说非常困难。
在 Tcl 中处理该问题的常用方法是将通道设置为非阻塞并侦听可读事件:
set fd [socket $server $port]
fconfigure $fd -blocking 0 -buffering line
fileevent $fd readable [list receive $fd]
# Send an initial string to the server
puts $fd Hello!
proc receive {fd} {
if {[eof $fd]} {
puts "The server closed the connection"
close $fd
exit
} else {
set data [read $fd]
if {$data ne ""} {
puts "Received: $data"
# Send a response back to the server
if {$data eq "Hey guys"} {
puts $fd "Hey you"
} else {
puts $fd "I don't understand $data"
}
}
}
}
# Run the event loop (not necessary when using Tk)
vwait forever
通过使通道不阻塞,read 命令将返回该时间点的所有可用数据。当有任何可用数据时触发可读事件。在连接后立即调用read 可能根本不会产生任何数据。所以这行不通。另一种方法是每 x 毫秒轮询一次,但效率很低。
注意:有人可能会指出上面的receive proc是不正确的,因为“必须在读取后检查eof”。但是那些人并没有完全掌握基于事件的文件处理。如果read 命令遇到文件或流的结尾,可读事件将立即再次触发。再次调用receive proc,然后处理文件结束条件。
【讨论】:
connection.sendall('Hello World') 的东西。因此没有 EOL。
read命令,但是如果numChars超过了消息的长度,tcl还是收不到。在我的情况下,来自 python 的消息的长度是不确定的。可能是 Hello World 或 Hey guy。
send -> python recv -> python 处理消息 -> python send -> tcl recv -> tcl next send 等。因此我不能使用@ 987654337@ 因为我还要发其他消息。