Two way communication between Unity and Python

1k Views Asked by At

So I want to send and receive from/to Unity and Python in the same run. I have the following components for the communication.

  1. TCPSendPipe - Sends data from Unity to Python
  2. TCPListePipe - Receives data from Python
  3. Python Script - Send (uses socket.connect) and Receive (uses socket.bind)

At the moment I can only use one at a time either, TCPSendPipe with Python receive or, TCPListenPipe with Python send

Following are the scripts:

  • TCPSendPipe.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using UnityEngine;


public class TCPSendPipe : MonoBehaviour
{
    public String Host = "localhost";
    public Int32 Port = 55000;

    TcpClient mySocket = null;
    NetworkStream theStream = null;
    StreamWriter theWriter = null;

    public GameObject robot;
    public Vector3 robPos;


    // Start is called before the first frame update
    void Start()
    {
        robot = GameObject.Find("robot");
        mySocket = new TcpClient();

        if (SetupSocket())
        {
            Debug.Log("socket is set up");
        }
    }

    // Update is called once per frame
    void Update()
    {
        robPos = robot.transform.position; 
        Debug.Log(robPos);
        if (!mySocket.Connected)
        {
            SetupSocket();
        }
        sendMsg();
    }

    public void sendMsg()
    {
        theStream = mySocket.GetStream();
        theWriter = new StreamWriter(theStream);
        //Byte[] sendBytes = System.Text.Encoding.UTF8.GetBytes("yah!! it works");
        Byte[] sendBytes = procData();
        mySocket.GetStream().Write(sendBytes, 0, sendBytes.Length);
    }

    public bool SetupSocket()
    {
        try
        {
            mySocket.Connect(Host, Port);
            Debug.Log("socket is sent");
            return true;
        }
        catch (Exception e)
        {
            Debug.Log("Socket error: " + e);
            return false;
        }
    }

    public Byte[] procData()
    {
        Byte[] bytes = new Byte[12]; // 4 bytes per float
 
        Buffer.BlockCopy( BitConverter.GetBytes( robPos.x ), 0, bytes, 0, 4 );
        Buffer.BlockCopy( BitConverter.GetBytes( robPos.y ), 0, bytes, 4, 4 );
        Buffer.BlockCopy( BitConverter.GetBytes( robPos.z ), 0, bytes, 8, 4 );
        return bytes;
    }

    private void OnApplicationQuit()
    {
        if (mySocket != null && mySocket.Connected)
            mySocket.Close();
    }
}

  • TCPListenPipe.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Globalization;
using System.Net.Sockets;
using UnityEngine;


public class TCPListenPipe : MonoBehaviour
{
    public String Host = "localhost";
    public Int32 Port = 55000;
    IPAddress localAddr = IPAddress.Parse("127.0.0.1");


    private TcpListener listener = null;
    private TcpClient client = null;
    private NetworkStream ns = null;
    string msg;

    // Start is called before the first frame update
    void Awake()
    {
        listener = new TcpListener(localAddr, Port);
        listener.Start();
        Debug.Log("is listening");

        if (listener.Pending())
        {
        client = listener.AcceptTcpClient();
        Debug.Log("Connected");
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (client == null)
        {
        if (listener.Pending())
        {
            client = listener.AcceptTcpClient();
            Debug.Log("Connected");
        }
        else
        {
            return;
        }
        }

        ns = client.GetStream();

        if ((ns != null) && (ns.DataAvailable))
        {
        StreamReader reader = new StreamReader(ns);
        msg = reader.ReadToEnd();
        float data = float.Parse(msg, CultureInfo.InvariantCulture);       
        Debug.Log(data);
        }
    }

    private void OnApplicationQuit()
    {
        if (listener != null)
        listener.Stop();
    }
}
  • Python Script
import socket
import struct
import numpy as np


class comm(object):

    TCP_IP = '127.0.0.1'
    TCP_PORT = 55000
    BUFFER_SIZE = 12  # Normally 1024, but we want fast response
    conn = []
    addr = []
    s = []

    def connect(self):
        self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.s.bind((self.TCP_IP, self.TCP_PORT))
        self.s.listen(1)
        self.conn, self.addr = self.s.accept()
        print ('Connection address:', self.addr)
    

    def receive(self):

        byte_data = self.conn.recv(self.BUFFER_SIZE)
        pos_data = np.array(np.frombuffer(byte_data, dtype=np.float32));
        #print("bytes data:", byte_data)
        print ("received data:", pos_data)
        #conn.close()
        return(pos_data)
    
    def send(self):
        cable_length = 25.123
        MESSAGE = str(cable_length)
        #MESSAGE = cable_length.tobytes()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((self.TCP_IP, self.TCP_PORT))
        #s.send(MESSAGE)
        s.send(MESSAGE.encode())
        s.close()
        return(MESSAGE)

So in order to send data from Unity to Python, I attach the TCPSendPipe.cs to the scene and within python script I just call receive after connecting.

comm_cl = comm()
comm_cl.connect()
while True:
    data = comm_cl.receive()

Whereas to send data from Python to Unity, I have to detach TCPSendPipe.cs and attach TCPListenPipe.cs to the scene and within python script I just call send (without connect since connect has socket.bind).

send_data = aa.send()

My purpose is to have a 2 way communication between Unity and Python. Can I use 2 different sockets to send and receive?, Is it even possible to create and connect to 2 different sockets at the same time? Any suggestions or ideas on achieveing this is greatly appreciated.

Thank You.

Can I use 2 different sockets to send and receive?, Is it even possible to create and connect to 2 different sockets at the same time?

0

There are 0 best solutions below