【发布时间】:2014-06-09 12:16:08
【问题描述】:
我目前正在使用 Blender3D 运行一个脚本,我在 Stackoverflow 的帮助下从 Python 2+ 移植到 Python 3+。该脚本在 OMRON PLC(可编程逻辑计算机)和 Blender/Python3+ 之间创建通信。该脚本使用 TCP 通信来写入和读取 PLC 的内存。移植后,脚本在 Blender 中正常运行,唯一的问题是它会产生大量延迟并迫使 Blender 以 6 fps 运行。
默认情况下,Python 套接字是阻塞的。这意味着当您调用
socket.read()时,该函数将不会返回,直到您的数据被读取或套接字上出现错误。即套接字“阻止”执行,直到操作完成。因为您的代码在recv()调用中被阻止,所以您的游戏冻结了。”LINK
链接中有说如果你添加setblocking(0)或setblocking(False)或settimeout(0)(都是一样的),你将取消由TCP通信引起的延迟。
为了使它工作,我不得不尝试将我的recv() 调用包装起来,除非为了避免套接字错误:BlockingIOError: [WinError 10035] A non-blocking socket operation could not be completed immediately。
我是这样做的:
def _recieve(self):
try:
pr = self.sock.recv(8)
length = binstr2int( pr[4:8])
r = pr + self.sock.recv( length)
#print (' Recv:' + repr(r))
return r
except socket.error as err:
# Any error but "Would block" should cause the socket to close
if err.errno != errno.EWOULDBLOCK:
self.sock.close()
self.sock = None
return
然而这并没有解决我的问题,这会产生更多的问题。当我有 setblocking(1) 时,该脚本将运行良好,但速度为 6fps。但是当我打开它时,它会给我一个 Indexerror:
File "D:\...", line 126, in disassembled
asm[ b'ICF'] = binstr2int( self.rawTcpFrame[16])
IndexError: index out of range'
这是发生错误的区域,如果我注释掉该行,它只会说错误发生在下一个self.rawTcpFrame[17] 例如:
def disassembled(self):
asm = {
b"header" : binstr2int( self.rawTcpFrame[ 0: 4] ),
b'length' : binstr2int( self.rawTcpFrame[ 4: 8] ),
b'command' : binstr2int( self.rawTcpFrame[ 8:12] ),
b'errCode' : binstr2int( self.rawTcpFrame[12:16] ),
}
if( asm[b'command'] == 2) :
asm[ b'ICF'] = binstr2int( self.rawTcpFrame[16])
asm[ b'RSV'] = binstr2int( self.rawTcpFrame[17])
asm[ b'GCT'] = binstr2int( self.rawTcpFrame[18])
asm[ b'DNA'] = binstr2int( self.rawTcpFrame[19])
asm[ b'DA1'] = binstr2int( self.rawTcpFrame[20])
asm[ b'DA2'] = binstr2int( self.rawTcpFrame[21])
asm[ b'SNA'] = binstr2int( self.rawTcpFrame[22])
asm[ b'SA1'] = binstr2int( self.rawTcpFrame[23])
asm[ b'SA2'] = binstr2int( self.rawTcpFrame[24])
asm[ b'SID'] = binstr2int( self.rawTcpFrame[25])
asm[ b'MRC'] = binstr2int( self.rawTcpFrame[26])
asm[ b'SRC'] = binstr2int( self.rawTcpFrame[27])
if self.fromRaw :
#decode from response
asm[ b'MRES'] = binstr2int( self.rawTcpFrame[28])
asm[ b'SRES'] = binstr2int( self.rawTcpFrame[29])
asm[b'response'] = self.rawTcpFrame[30:]
else :
asm[b'cmd'] = self.rawTcpFrame[28:]
return asm
整个脚本可以在here.找到
【问题讨论】:
-
我不确定我是否做对了,但这会导致更多错误。我已经尝试将它们包装在 try 中,但是这会与其他东西混淆:
File "D:\...", line 177, in __str__ return b''.join([ k + b':' + bytes(str(asm[k]), 'utf-8') + b' ' for k in list(asm.keys())]).decode('utf-8') AttributeError: 'NoneType' object has no attribute 'keys'
标签: python sockets tcp blender