Python和TCL之间的套接字连接
Socket connection between Python and TCL
我刚刚开始进行套接字编程。我想让客户端作为 TCL,服务器作为 Python。我尝试了以下几个脚本,但我无法取得任何进展。
这是我的脚本:
server.py:
import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 45000))
s.listen(5)
while True:
clt, adr=s.accept()
print(adr)
clt.send(bytes("Socket programming in Python"))
client.tcl:
set host "127.0.0.1"
set port 45000
set mysock [socket -myaddr $host -myport $port $host $port]
fconfigure $mysock -buffering none
gets $mysock line
close $mysock
puts "Message is $line"
但是,上面的TCL脚本只是挂了,并没有超出gets命令的范围。
这是有效的等效 Python 客户端脚本:
client.py:
import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print(s)
s.connect((socket.gethostname(), 45000))
msg=s.recv(1024)
print(msg.decode("utf-8"))
现在根据一些建议,为了在 TCL 中模仿上述 python 客户端脚本,我尝试了以下操作:
client_modified.tcl:
set s [socket [info hostname] 45000]
puts $s
fconfigure $s -translation binary
puts [encoding convertfrom utf-8 [read $s 28]]
我仍然无法继续:“socket localhost 45000”。
它给我错误:
> tclsh client.tcl
couldn't open socket: connection refused
while executing
"socket [info hostname] 45000"
invoked from within
"set s [socket [info hostname] 45000]"
哪位大神能指导一下吗
在 Tcl 端,要打开客户端套接字,请不要指定 -myport
。此选项指定客户端连接要使用的特定端口。由于您的代码将其设置为服务器已在使用的端口 45000,因此失败。
set host "127.0.0.1"
set port 45000
try {
set mysock [socket $host $port]
} on error { err res } {
puts $res
}
try {
chan configure $mysock -buffering line
chan configure $mysock -encoding utf-8
} on error { err res } {
puts $res
}
try {
gets $mysock line
} on error { err res } {
puts $res
}
puts "Message is $line"
close $mysock
我更改了 python 代码以包含换行符,以便刷新消息。不知道任何 python 或 python 套接字代码如何工作,我在那里很幸运。
import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 45000))
s.listen(5)
while True:
clt, adr=s.accept()
print(adr)
clt.send(bytes("Socket programming in Python\n"))
鉴于:
import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print(s)
s.connect((socket.gethostname(), 45000))
msg=s.recv(1024)
print(msg.decode("utf-8"))
是一个working Python客户端,在Tcl中等价的是:
set s [socket [info hostname] 45000]
puts $s
fconfigure $s -translation binary
puts [encoding convertfrom utf-8 [read $s 28]]; # You're writing 28 bytes, not 1024
但我更倾向于写:
set s [socket localhost 45000]; # For complex reasons, [info hostname] takes a long time on macOS
fconfigure $s -encoding utf-8
puts [read $s 28]
请注意,如果您通过套接字写入文本数据,您真的还应该写入换行符作为消息边界。在 Tcl 方面,这将允许您使用 gets
而不是 read
;如果没有换行符,Tcl 的 gets
将在默认阻塞模式下无限期地等待它出现。 (对于面向二进制的协议,如果它是可变的,您可能会首先发送数据的长度。)
更复杂的版本使用非阻塞模式。除非你真的确定你在做什么,非阻塞模式应该专门用于 fileevent
回调:
set s [socket localhost 45000]
fconfigure $s -encoding utf-8 -blocking 0
fileevent $s readable {apply {{} {
global s done
puts [read $s 1024]
# Remember to close that socket at EOF
if {[eof $s]} {
close $s
set done "ok"; # Terminates the event loop running this
}
}}}
vwait done; # Launch an event loop for processing the socket
如果您将消息写回服务器,您可能需要设置 -buffering none
,这样您就不必为 flush
操心了。如果您正在进行复杂的对话,您可能希望使用协程来管理它;他们具有复杂编程的功能(并且存在一些支持库来提供帮助),这使得复杂的协议变得非常简单。
它适用于以下小编辑(-async):
set s [socket -async [info hostname] 45000]
puts $s
fconfigure $s -translation binary
puts [encoding convertfrom utf-8 [read $s 28]]
感谢您的帮助。
我刚刚开始进行套接字编程。我想让客户端作为 TCL,服务器作为 Python。我尝试了以下几个脚本,但我无法取得任何进展。
这是我的脚本:
server.py:
import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 45000))
s.listen(5)
while True:
clt, adr=s.accept()
print(adr)
clt.send(bytes("Socket programming in Python"))
client.tcl:
set host "127.0.0.1"
set port 45000
set mysock [socket -myaddr $host -myport $port $host $port]
fconfigure $mysock -buffering none
gets $mysock line
close $mysock
puts "Message is $line"
但是,上面的TCL脚本只是挂了,并没有超出gets命令的范围。
这是有效的等效 Python 客户端脚本:
client.py:
import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print(s)
s.connect((socket.gethostname(), 45000))
msg=s.recv(1024)
print(msg.decode("utf-8"))
现在根据一些建议,为了在 TCL 中模仿上述 python 客户端脚本,我尝试了以下操作:
client_modified.tcl:
set s [socket [info hostname] 45000]
puts $s
fconfigure $s -translation binary
puts [encoding convertfrom utf-8 [read $s 28]]
我仍然无法继续:“socket localhost 45000”。
它给我错误:
> tclsh client.tcl
couldn't open socket: connection refused
while executing
"socket [info hostname] 45000"
invoked from within
"set s [socket [info hostname] 45000]"
哪位大神能指导一下吗
在 Tcl 端,要打开客户端套接字,请不要指定 -myport
。此选项指定客户端连接要使用的特定端口。由于您的代码将其设置为服务器已在使用的端口 45000,因此失败。
set host "127.0.0.1"
set port 45000
try {
set mysock [socket $host $port]
} on error { err res } {
puts $res
}
try {
chan configure $mysock -buffering line
chan configure $mysock -encoding utf-8
} on error { err res } {
puts $res
}
try {
gets $mysock line
} on error { err res } {
puts $res
}
puts "Message is $line"
close $mysock
我更改了 python 代码以包含换行符,以便刷新消息。不知道任何 python 或 python 套接字代码如何工作,我在那里很幸运。
import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 45000))
s.listen(5)
while True:
clt, adr=s.accept()
print(adr)
clt.send(bytes("Socket programming in Python\n"))
鉴于:
import socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print(s)
s.connect((socket.gethostname(), 45000))
msg=s.recv(1024)
print(msg.decode("utf-8"))
是一个working Python客户端,在Tcl中等价的是:
set s [socket [info hostname] 45000]
puts $s
fconfigure $s -translation binary
puts [encoding convertfrom utf-8 [read $s 28]]; # You're writing 28 bytes, not 1024
但我更倾向于写:
set s [socket localhost 45000]; # For complex reasons, [info hostname] takes a long time on macOS
fconfigure $s -encoding utf-8
puts [read $s 28]
请注意,如果您通过套接字写入文本数据,您真的还应该写入换行符作为消息边界。在 Tcl 方面,这将允许您使用 gets
而不是 read
;如果没有换行符,Tcl 的 gets
将在默认阻塞模式下无限期地等待它出现。 (对于面向二进制的协议,如果它是可变的,您可能会首先发送数据的长度。)
更复杂的版本使用非阻塞模式。除非你真的确定你在做什么,非阻塞模式应该专门用于 fileevent
回调:
set s [socket localhost 45000]
fconfigure $s -encoding utf-8 -blocking 0
fileevent $s readable {apply {{} {
global s done
puts [read $s 1024]
# Remember to close that socket at EOF
if {[eof $s]} {
close $s
set done "ok"; # Terminates the event loop running this
}
}}}
vwait done; # Launch an event loop for processing the socket
如果您将消息写回服务器,您可能需要设置 -buffering none
,这样您就不必为 flush
操心了。如果您正在进行复杂的对话,您可能希望使用协程来管理它;他们具有复杂编程的功能(并且存在一些支持库来提供帮助),这使得复杂的协议变得非常简单。
它适用于以下小编辑(-async):
set s [socket -async [info hostname] 45000]
puts $s
fconfigure $s -translation binary
puts [encoding convertfrom utf-8 [read $s 28]]
感谢您的帮助。