我有一个TCP客户机与LabVIEW图形用户界面通信。
我的程序在开始时调用connect()
,在结束时调用disconnect()
。它将调用passCommand(x)
来向labview gui读取或写入数据。但是,在某些情况下,我有多个线程可能在调用passCommand()
并且返回数据会被混淆。
例如,在主线程中,我将要求电压,它应该是一个300到400之间的数字。在另一条线中,我会问温度,它应该是0-100之间的一个数字。电压将返回25,而温度将得到250。
这是TCP通信和线程的已知问题吗?有没有一种方法可以解决这个问题,比如实现一个队列或者唯一的ID或者其他什么?
import socket as _socket
# get python major version as integer
from sys import version as pythonVersion
pythonVersionMajor = int(pythonVersion[0])
_serverHost = 'localhost'
_serverPort = 50007
isConnected = 0
_sockobj = None
_error_string = "error:"
def connect():
'opens a connection to LabVIEW Server'
global _sockobj, isConnected
_sockobj = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM) # create socket
_sockobj.connect((_serverHost, _serverPort)) # connect to LV
isConnected = 1
def disconnect():
'closes the connection to LabVIEW Server'
global isConnected
_sockobj.close() # close socket
isConnected = 0
def passCommand(command):
'passes a command to LabVIEW Server'
## We prepend the command length (8 char long) to the message and send it to LV
# Compute message length and pad with 0 on the left if required
commandSize=str(len(command)).rjust(8,'0')
# Prepend msg size to msg
completeCommand=commandSize+command
# python 3 requires data to be encoded
if (pythonVersionMajor >= 3):
completeCommand = str.encode(completeCommand)
# Send complete command
_sockobj.send(completeCommand)
data = _sockobj.recv(11565536)
# python 3 requires data to be decoded
if (pythonVersionMajor >= 3):
data = bytes.decode(data)
if data.rfind(_error_string) == 0:
error = True
data = data[len(_error_string):] # get data after "error:" string
else:
error = False
execString = "lvdata = " + data
exec(execString, globals())
if error:
raise _LabVIEWError(lvdata)
else:
return lvdata
class _Error(Exception):
"""Base class for exceptions in this module."""
pass
class _LabVIEWError(_Error):
"""Exception raised for errors generated in LabVIEW.
Attributes:
code -- LabVIEW Error Code
source -- location of the error
message -- explanation of the error
"""
def __init__(self, error):
self.code = error[0]
self.source = error[1]
self.message = error[2]
def __str__(self):
return "%s" % (self.message,)
最佳答案
这是线程最常见问题之一的示例。您正在从多个线程访问一个资源,该资源不被认为是线程安全的(如果两个线程同时发送/接收,则一个线程可能得到错误的响应,甚至两个响应)。
理想情况下,您应该使用互斥锁锁定对passcommand的访问,以便一次只能由一个线程使用passcommand,或者为每个线程打开一个套接字,或者在一个线程中执行所有套接字操作。