在unity3d中使用套接字有问题

时间:2018-04-10 15:03:37

标签: c# python sockets unity3d

制作一个与python脚本通信的Hololens应用程序。 python脚本以JSON的形式将PLC(西门子S7-1200)变量发送到hololens。 C#脚本处理JSON。当脚本从plc读取数据时,也可以使用C#脚本中的sendMessage方法控制变量。我制作了一个单独的python脚本来控制plc,我不会分享。

我的Unity3d C#脚本:

import socket,time
from read import CustOPCLib


class BroadcastServer(object):
    def __init__(self,host,port):
        self._host = host
        self._port = port
        self.sock = None
    def connect(self):
        self.sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
        self.sock.connect((self._host,self._port))
    def sendMsg(self,msg):
        self.sock.send(msg.encode('utf8'))
    def disconnect(self):
        self.sock.close()

if __name__ == '__main__':
    c = CustOPCLib()
    c.connect()
    Host = '172.16.24.174'
    Port = 8000
    ser = BroadcastServer(Host,Port)
    ser.connect()
    msg = 'test'
    i = 0
    while True:
        i = i + 1
        msg += (str(i))
        ser.sendMsg(c.opcjson())
        time.sleep(0.25)
    ser.disconnect()

这是我的python服务器代码:

from opcua import ua, Client
import json

'''This class makes connection to the OPC-UA server, and has functions that can be used to return the current values of a specific
variable'''
class ReadVariables(object):
    '''init function, contains the node locations of the OPC-UA server'''
    def __init__(self):
        self.jsonobj = {}
        self.Index = "ns=7;s=S7-1200 station_2.PLC_OPC_HOLOLENS.DATA.Index"
        self.Moto = "ns=7;s=S7-1200 station_2.PLC_OPC_HOLOLENS.MOTO"
        self.Start = "ns=7;s=S7-1200 station_2.PLC_OPC_HOLOLENS.START"
        self.StartWincc = "ns=7;s=S7-1200 station_2.PLC_OPC_HOLOLENS.STARTWINCC"
        self.Stop = "ns=7;s=S7-1200 station_2.PLC_OPC_HOLOLENS.STOP"
        self.StopWINCC = "ns=7;s=S7-1200 station_2.PLC_OPC_HOLOLENS.STOPWINCC"
        self.Tag_1 = "ns=7;s=S7-1200 station_2.PLC_OPC_HOLOLENS.Tag_1"
        self.Tag_2 = "ns=7;s=S7-1200 station_2.PLC_OPC_HOLOLENS.Tag_2"
        self.client = None

    '''This function connects to the OPC-UA server'''
    def connect(self):
        print("Connecting to OPC-UA server")
        self.client = Client("opc.tcp://Wilrik-PC:4845")
        self.client.connect()
        print("Connected to OPC-UA server") 

    '''This function can be used to disconnect from the OPC-UA server'''
    def disconnect(self):
        print("Disconnecting from OPC-UA server")
        self.client.disconnect()

    '''This function returns the root node on the OPC-server'''
    def get_root_node(self):
        root = self.client.get_root_node()
        print("Root node is:", root)
        return root

    '''This function returns the objects node on the OPC-server'''
    def get_objects_node(self):
        objects = self.client.get_objects_node()
        print("Objects node is: ",objects)
        return objects

    '''This function returns the children of the objects node on the OPC-server'''
    def get_objects_node_children(self):
        objects = self.client.get_objects_node()
        print("children of objects node is:",objects.get_children())
    ################################################# VARIABLES ###########################################################
    '''This function returns the value of the index variable on the OPC-server'''
    def index(self):
        index = self.client.get_node(self.Index)
        return index.get_value()

    '''This function returns the value of the moto variable on the OPC-server'''
    def moto(self):
        moto = self.client.get_node(self.Moto)
        return moto.get_value()

    '''This function returns the value of the start variable on the OPC-server'''
    def start(self):
        start = self.client.get_node(self.Start)
        return start.get_value()

    '''This function returns the value of the startwincc variable on the OPC-server'''
    def startwincc(self):
        startwincc = self.client.get_node(self.StartWincc)
        return startwincc.get_value()

    '''This function returns the value of the stop variable on the OPC-server'''
    def stop(self):
        stop = self.client.get_node(self.Stop)
        return stop.get_value()

    '''This function returns the value of the stopwincc variable on the OPC-server'''
    def stopwincc(self):
        stopwincc = self.client.get_node(self.StopWINCC)
        return stopwincc.get_value()

    '''This function returns the value of the Tag_1 variable on the OPC-server'''
    def tag_1(self):
        tag1 = self.client.get_node(self.Tag_1)
        return tag1.get_value()

    '''This function returns the value of the Tag_2 variable on the OPC-server'''
    def tag_2(self):
        tag2 = self.client.get_node(self.Tag_2)
        return tag2.get_value()
    ################################################# VARIABLES ###########################################################

    ################################################# JSON ################################################################
    def opcjson(self):
        self.jsonobj['Index'] = self.index()
        self.jsonobj['Moto'] = self.moto()
        self.jsonobj['Start'] = self.start()
        self.jsonobj['StartWINCC'] = self.startwincc()
        self.jsonobj['Stop'] = self.stop()
        self.jsonobj['StopWINCC'] = self.stopwincc()
        self.jsonobj['Tag1'] = self.tag_1()
        self.jsonobj['Tag2'] = self.tag_2()
        obj = json.dumps(self.jsonobj)
        return self.jsonobj
    ################################################# JSON ################################################################

这是读取脚本(p.opcjson()中的脚本):

{{1}}

更新1:应用DoctorPangloss的建议,当我开始工作时,它仍然没有按照我想要的方式工作。我目前的情况:我启动我的Unity3d应用程序,然后我启动我的python应用程序,unity接收数据,我关闭python脚本并重新启动它,我只接收一次数据,然后挂起。

更新2:删除了问题,将为那些可以使用它的人留下这个。这并不包含控制脚本,您必须自己制作。

1 个答案:

答案 0 :(得分:2)

你的问题在于这一行:

Debug.Log("client message received as: " + clientMessage);

您无法从另一个线程(即您的侦听线程)访问Unity线程(即Unity对象)。将收到的包排入ConcurrentQueue queue,然后从queue出列,直到Update函数内的每一帧都为空。

您的第二个问题是ConcurrentQueue实施。这是不对的。你发现它的地方有这样的评论:

  

这不是ConcurrentQueue ..而只是队列+锁

https://gist.github.com/jaredjenkins/5421892

尝试调整真正的并发队列实现,如下所示: https://github.com/mono/mono/blob/master/mcs/class/referencesource/mscorlib/system/collections/Concurrent/ConcurrentQueue.cs。使用TryDequeue(out item)实际出列,而不是偷看或Dequeue

你的第三个问题是:

using (NetworkStream stream = connectedTcpClient.GetStream())
                {
                    int length;
                    // Read incomming stream into byte arrary.                      
                    while ((length = stream.Read(bytes, 0, bytes.Length)) != 0)

TCP不是消息传递协议。如果要发送消息,请使用Web套接字,或者将要从一个地方发送到另一个地方的内容的长度作为长度前缀,即使它只是字符串。这不一定会咬你,但会在以后发生。

您的第四个问题是p.opcjson()。也许读一次,并将其保存到变量?它可能会在第二次通话时阻塞,意外;我不确定这里发生了什么。

总的来说,我认为你的C#监听代码和你的Python代码都可能存在问题。不幸的是,编写自己的TCP套接字代码非常容易出错。考虑使用Asset Store和Python中的Web套接字,其语义更加直观。