valkjsaaa / Unity-ZeroMQ-Example

An example of Unity 3D 2017 works with NetMQ
78 stars 28 forks source link

Unity 2018 Client with Bind and Server Connect (from computer to computer not working) #9

Closed alessandrolopopolo closed 5 years ago

alessandrolopopolo commented 6 years ago

Hi, I tried to change the code with unity 2018 and I noticed that everything works correctly in localhost but when I try to modify the code by making the client bind and the server connect locally it works but from computer to computer no . Can you help me?

` public class NetMqListenerTest { private readonly Thread _listenerWorker;

private bool _listenerCancelled;

public delegate void MessageDelegate(string message);

private readonly MessageDelegate _messageDelegate;

private readonly ConcurrentQueue<string> _messageQueue = new ConcurrentQueue<string>();

private void ListenerWork()
{
    AsyncIO.ForceDotNet.Force();
    Debug.Log(" ListenerWork");

    using (var subSocket = new SubscriberSocket())
    {
        Debug.Log(" SubscriberSocket");

        //subSocket.Options.ReceiveHighWatermark = 1000;
        subSocket.Bind("tcp://192.168.2.121:9367");
       // subSocket.Bind("tcp://localhost:9367");
      //  subSocket.Connect("tcp://localhost:12345");
        subSocket.Subscribe("");

        Debug.Log(" subSocket.Subscribe");
        Debug.Log("_listenerCancelled : "+_listenerCancelled);

        while (!_listenerCancelled)
        {
            string frameString;
           // Debug.Log("frameString : "+subSocket.TryReceiveFrameString(out frameString));
            Debug.Log("frameString :");
            if (!subSocket.TryReceiveFrameString(out frameString)) continue;
            Debug.Log(frameString);
            _messageQueue.Enqueue(frameString);
        }
        subSocket.Close();
        Debug.Log(" Close");

    }
    NetMQConfig.Cleanup();
    Debug.Log(" Cleanup");

}

public void Update()
{
    while (!_messageQueue.IsEmpty)
    {
        string message;
        if (_messageQueue.TryDequeue(out message))
        {
            _messageDelegate(message);
        }
        else
        {
            break;
        }
    }
}

public NetMqListenerTest(MessageDelegate messageDelegate)
{
    _messageDelegate = messageDelegate;
    _listenerWorker = new Thread(ListenerWork);
    Debug.Log(" NetMqListenerTest _listenerWorker");

}

public void Start()
{
    _listenerCancelled = false;
    _listenerWorker.Start();
    Debug.Log(" _listenerWorker Start");

}

public void Stop()
{
    _listenerCancelled = true;
    _listenerWorker.Join();
    Debug.Log(" _listenerWorker Stop");

}

}

public class Test : MonoBehaviour { private NetMqListenerTest _netMqListener;

private void HandleMessage(string message)
{
    Debug.Log("Message: "+message);
}

private void Start()
{
    Debug.Log("Start");
    _netMqListener = new NetMqListenerTest(HandleMessage);
    _netMqListener.Start();
    Debug.Log(" _netMqListener Start");

}

private void Update()
{
    _netMqListener.Update();
}

private void OnDestroy()
{
    _netMqListener.Stop();
}

} `

server: `#! /usr/local/bin/python3 import zmq import time import random context = zmq.Context() socket = context.socket(zmq.PUB) hostname = "192.168.2.121" socket.connect('tcp://%s:9367' % hostname)

while True: message = str(random.uniform(-1.0, 1.0)) + " " + str(random.uniform(-1.0, 1.0)) + " " + str(random.uniform(-1.0, 1.0)) socket.send_string(message) print(message) time.sleep(1)`

valkjsaaa commented 6 years ago

It's not tested for the listener to bind. I suggest you make your python server (publisher) to bind and your C# script to connect.

Also, check out your local firewall or router settings and makes sure that you can establish a connection between those two machines. I would suggest you start from writing a client and a server both in Python and after it works, transition the client into C# code.

Let me know if it works :)

alessandrolopopolo commented 6 years ago

thank you very much for my needs the script that sends the connect and the other script binds. I tested the example scripts and with unity works between pc and pc it does not work when I ask to bind

valkjsaaa commented 5 years ago

I find bind on Unity side is quite hard. If you figured it out, please let me know 😉

alessandrolopopolo commented 5 years ago

I found the solution to make the Bind work on two different PCs. The real problem is that I did not understand why! If I disable the firewall everything works, then I tried to enable the port to give all the permissions on the ports but nothing works only with firewalls disabled and this problem persists even if I create a simple TCP socket with unity. Can someone explain to me why?

Example TCP server:

public class MyTcpListener : MonoBehaviour
{
    private Thread _thread;

    private TcpListener server;

    [SerializeField] private int port;
    [SerializeField] private string ip;
    // Start is called before the first frame update
    void Start()
    {
        try
        {
            _thread  = new Thread(ThreadWorks);
            _thread.Start();

        }
        catch(SocketException e)
        {
            Debug.Log("SocketException: " + e.Message);
        }

        Debug.Log("Hit enter to continue...");

    }

    private void ThreadWorks()
    {

        try
        {
            //Int32 port = 5555;
            IPAddress localAddr = IPAddress.Parse(ip);

            // TcpListener server = new TcpListener(port);
            server = new TcpListener(localAddr, port);

            // Start listening for client requests.
            server.Start();
            Debug.Log("server start at : "+ip+":"+port );
            // Buffer for reading data
            Byte[] bytes = new Byte[256];
            String data = null;
            // Enter the listening loop.
            while(true) 
            {
                Debug.Log("Waiting for a connection... ");

                // Perform a blocking call to accept requests.
                // You could also user server.AcceptSocket() here.
                TcpClient client = server.AcceptTcpClient();            
                Debug.Log("Connected!");

                data = null;

                // Get a stream object for reading and writing
                NetworkStream stream = client.GetStream();

                int i;

                // Loop to receive all the data sent by the client.
                while((i = stream.Read(bytes, 0, bytes.Length))!=0) 
                {   
                    // Translate data bytes to a ASCII string.
                    data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
                    Debug.Log("****** Server Received: " + data);

                    // Process the data sent by the client.
                    data = data.ToUpper();

                    byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);

                    // Send back a response.
                    stream.Write(msg, 0, msg.Length);
                    Debug.Log("Server send back a response -> Sent: " + data);            
                }

                // Shutdown and end connection
                client.Close();
            }

        }
        catch(SocketException e)
        {
            Debug.Log("SocketException: "+ e.Message);
        }
        finally
        {
            // Stop listening for new clients.
            server.Stop();
        }

    }

    private void OnDestroy()
    {
        server.Stop();
    }

    // Update is called once per frame
    void Update()
    {

    }
}
alessandrolopopolo commented 5 years ago

I do not know why but I noticed that the build of the example goes without problems is only the debug mode of unity that problems with the firewall is probably not enabled something but I have not yet figured out what, if someone scans why you let me know

valkjsaaa commented 5 years ago

Interesting. Have you grant UnityEditor.exe network access?

alessandrolopopolo commented 5 years ago

I checked and indeed unity editor has no constraints, while the editor with version 2018 ... has the constraint for private networks, removed that constraint works all. Thank you so much for the support