2012-01-25 2 views
1

LabVIEW GUI와 통신하는 TCP 클라이언트가 있습니다.TCP 클라이언트 읽기/쓰기 중첩 문제는 어떻게 관리합니까?

내 프로그램은 처음에 connect()을 호출하고 끝에 disconnect()을 호출합니다. passCommand(x)을 호출하여 LabVIEW GUI에 데이터를 읽거나 쓸 수 있습니다. 그러나 경우에 따라 passCommand()을 호출 할 수있는 여러 스레드가 있는데 어떻게 든 리턴 데이터가 섞일 수 있습니다.

예를 들어, 주 스레드에서 300 ~ 400 사이의 숫자 여야하는 전압을 묻습니다. 다른 스레드에서 온도를 묻습니다.이 온도는 0-100 사이의 숫자 여야합니다. 전압은 250으로 반환되지만 온도는 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,) 

답변

4

이것은 스레딩에서 가장 일반적인 문제 중 하나의 예입니다. 여러 스레드에서 리소스에 액세스하고 리소스가 스레드 안전성으로 간주되지 않습니다 (두 스레드가 동시에 보내거나받는 경우 스레드가 잘못된 응답을 받거나 심지어 모두 응답).

뮤텍스와 함께 passCommand에 대한 액세스를 잠그는 것이 이상적입니다. 한 번에 하나의 스레드 만 사용할 수 있거나 스레드 당 하나의 소켓을 열거 나 단일 스레드에서 모든 소켓 작업을 수행 할 수 있습니다.

+0

뮤텍스를 추가하면 약간 느려지지만 문제가 해결됩니다. 감사 – user1170193