zeromq / netmq

A 100% native C# implementation of ZeroMQ for .NET
Other
2.96k stars 744 forks source link

Unity get stuck #526

Closed hojjatjafary closed 4 years ago

hojjatjafary commented 8 years ago

I created a simple Request/Reply sockets in Unity 5.3.1 but it only works for the first time, the second time that I press Play button the Unity hangs and I need to close it using Windows task manager. I build the NetMq using the last source code, here is my script.

using UnityEngine;
using System;

using NetMQ;
using NetMQ.Sockets;

public class ReqRep : MonoBehaviour
{
    // Use this for initialization
    void Start ()
    {
        Debug.Log("Start.");
        AsyncIO.ForceDotNet.Force();
        string address = "tcp://127.0.0.1:8833";
        using (var rep = new ResponseSocket())
        using (var req = new RequestSocket())
        {
            rep.Options.Linger = TimeSpan.Zero;
            req.Options.Linger = TimeSpan.Zero;
            rep.Bind(address);
            req.Connect(address);

            req.SendFrame("Hi");

            Debug.Log(rep.ReceiveMultipartStrings()[0]);

            rep.SendFrame("Hi2");

            Debug.Log(req.ReceiveMultipartStrings()[0]);
        }

        Debug.Log("End.");
    }

}
hojjatjafary commented 8 years ago

PS: This code works properly on a simple console application.

MikeFair commented 8 years ago

I've tried to look into these issues myself; I have no concrete answers at this time, but I do have some guidance to help try to isolate what's happening.

I've started building the project from GitHub and haven't used the Nuget repositories in a while so I can't say whether those are working or not. So I'd suggest doing a Github pull of the project and building the NetMQ35 project locally.

1) Ensure the ASyncIO reference for the NetMQ35 project is using the net35 folder; I don't know if it makes a difference or not, but it keeps the framework references consistent. I just discovered this one for certain today, so it could be this alone has been the whole problem.

2) After you build the NetMQ35 project, copy those DLLs into the Unity Assets folder (I use a post-build step to copy the DLLs into a subtree I use to keep things managed).

3) Using only one Socket and "Connect"ing externally seems to work fine. Using multiple sockets seems to be where things go awry. Try again using your console application to respond and Unity to request (just comment out the respective using/new/networkCommands parts) and see if that works.

4) Using only one Socket I've made Bind work and connected to it from an external application. Try the same single socket experiment again, but this time with Unity as the Responder and using your console app as the Requestor.

5) I'm not sure but today (while I was using the Beacon Demo) using tcp://* or tcp://0.0.0.0 only seemed to listen on the first network interface which is an unplugged ethernet cable. It had never occured to me that tcp://* wouldn't automatically listen to all interfaces; so a lot of my testing could be invalid. I suggest using the hardcoded IP of the interface you want to work with for now.

6) Connecting the Visual Studio debugger to Unity seems to also create further problems. I've seen packets being sent and/or received using a packet sniffer, and then as soon as I connect the debugger, the packets stop (no breakpoints, just the connection).

7) It just occurred to me today to try copying the source tree for NetMQ35 into the Unity Assets folder so the Unity project can build the NetMQ source in the context of the Unity framework profile straight into the project's code libraries. I have no clue if it will help but I can't see it hurting anything.

Would love to hear back from you if you do try any of the above.

Thanks and Good Luck

hojjatjafary commented 8 years ago

Thank you Mark, I tried these:

1) I built both the projects from source, ASyncIO and NetMQ, and I'm sure about there correct references.

2) I ensured that the copies are correct.

3, 4) Doesn't worked.

5) I'm using hardcoded IP.

6) I didn't use the Visual Studio debugger..

I cleared all sending and receiving codes but the issue remains:

using UnityEngine;
using System;

using NetMQ;
using NetMQ.Sockets;

public class ReqRep : MonoBehaviour
{
    // Use this for initialization
    void Start()
    {
        Debug.Log("Start.");

        AsyncIO.ForceDotNet.Force();
        using (ResponseSocket rep = new ResponseSocket("tcp://192.168.1.4:8833"))
        {

        }

        Debug.Log("End.");
    }

}

Thanks, Hojjat.

somdoron commented 8 years ago

I also tried to figure this out, the best I can suggest is to use version 3.X and use NetMQContext, make sure to close it when the application exit.

I will add a method to kill the content the contextless NetMQ 4.0 is using.

MikeFair commented 8 years ago

Hi Hojjat,

Oh, and as @somdoron mentioned; I am using the earlier "NetMQContext" method; not the more recent "Contextless" versions. But that's more because the code I had was built before the "Contextless" approach existed. To make this work on multiple objects I made a single gameObject which created the context ("NetworkBus") and all other scripts located the NetworkBus and requested the Context object that it created. I've never been able to make Unity exit without crashing if I created a TCP socket... I'd love to hear back if you were able to not crash on exit. :)

What I meant was rather than do both request and response in the same object on two sockets; just put one side in the start method (a request version, then a response version).

The request version would be:

using UnityEngine;
using System;

using NetMQ;
using NetMQ.Sockets;

public class ReqRep : MonoBehaviour
{
    // Use this for initialization
    void Start()
    {
        Debug.Log("Start.");
        AsyncIO.ForceDotNet.Force();

        string address = "tcp://192.168.1.4:8833";

        using (var req = new RequestSocket(address))
        // The console app provides the response messages
        {
            req.Options.Linger = TimeSpan.Zero;
            req.Connect(address);

            req.SendFrame("Hi");
            Debug.Log(req.ReceiveMultipartStrings()[0]);
        }

        Debug.Log("End.");
    }

}

The response version would be:

using UnityEngine;
using System;

using NetMQ;
using NetMQ.Sockets;

public class ReqRep : MonoBehaviour
{
    // Use this for initialization
    void Start()
    {
        Debug.Log("Start.");
        AsyncIO.ForceDotNet.Force();

        string address = "tcp://192.168.1.4:8833";

        using (var rep = new ResponseSocket(address))
        // The console app issues the request messages
        {
            rep.Options.Linger = TimeSpan.Zero;
            rep.Bind(address);
            Debug.Log(rep.ReceiveMultipartStrings()[0]);

            rep.SendFrame("Hi2");
        }

        Debug.Log("End.");
    }
}

Also, I've had success using the "inproc" method to communicate to gameobjects within Unity but that's obviously just communicating within the single Unity process; not outside to other applications.

dgsantana commented 8 years ago

With the new version, since the Context termination only happens when the application exit's (NetMQConfig line 22), in Unity we never see this happen in the editor, that's the reason for not working. One way is to patch the NetMQConfig to allow for a call to Ctx.Terminate, but not a good practice for applications outside the Unity3D world.

hojjatjafary commented 8 years ago

Thank you @dgsantana, it was better if we had some control over context termination.

MikeFair commented 8 years ago

Are the resources (like the listening thread/process) for multiple NetMQ applications shared in the same DLL Context object? If so, the call should obviously only affect the resources of the app that made the call. It seems it's more of a Clear() call freeing resources associated with the calling application. On Apr 22, 2016 4:51 AM, "Hojjat" notifications@github.com wrote:

Thank you @dgsantana https://github.com/dgsantana, it was better if we had some control over context termination.

— You are receiving this because you commented. Reply to this email directly or view it on GitHub https://github.com/zeromq/netmq/issues/526#issuecomment-213391918

dgsantana commented 8 years ago

I did some patching on my local branch, and even a "clear" call doesn't seem to solve totally. Because you also need to create the Context for the next Unity3D editor play, and I also did that. But there are more threading issues that I couldn't find yet. In the end, I was able to not crash the editor, but I got errors in the internal mailbox of NetMQ, and the NetMQ system wasn't in a proper stable state after the first editor play.

MikeFair commented 8 years ago

That sounds like a great start! Deeper than I was able track! Great work!

I'm a bit confused though because Clear() should leave the Context alone and just Close/dispose all the sockets.

However there's an alternative; what if you register/Request a Named Context using something like NetMQ.RequestContext("Unity") / NetMQ.StopContext("Unity") / NetMQ.StartContext("Unity").

Each object would use RequestContext("contextName") to get a ctx object or supply the context name within which to create the socket in the call to new.

The contextname would pull the context from a dictionary managed by NetMQ. Tgis way the default context is never used; and its generically useful to supply a way for code using multiple different contexts to use the proposed "new" syntax. It would also help me get rid of a singleton object I created in Unity just to keep track of the game's context object.

If NetMQ was providing a way to register a context a refer to/start/stop it when required; that could solve a number of potential use cases...

?

Mike On Apr 22, 2016 1:23 PM, "Daniel Santana" notifications@github.com wrote:

I did some patching on my local branch, and even a "clear" call doesn't seem to solve totally. Because you also need to create the Context for the next Unity3D editor play, and I also did that. But there are more threading issues that I couldn't find yet. In the end, I was able to not crash the editor, but I got errors in the internal mailbox of NetMQ, and the NetMQ system was in a proper stable after the first editor play.

— You are receiving this because you commented. Reply to this email directly or view it on GitHub https://github.com/zeromq/netmq/issues/526#issuecomment-213576623

dgsantana commented 8 years ago

Sounds like an interesting approach @MikeFair . But may require some rewrite of NetMQ new code to pass a named context's, in the socket's constructor (optionally). I will track the use of the internal NetMQConfig.Context to see how deep is the rabbit hole.

My solution was just in the NetMQConfig. I added to 3 new methods, one was RequiresManualContextTermination, that "disables" the ProcessExit event registered on the static constructor, a ManualTerminateContext(bool block=true) that terminates the context, setting if it should block or not, and a ManualCreateContext(), for creating a context (needed when you terminate, and need to create a new one, e.g when pressing play the second time in the Unity Editor). All of this just works, if you call the RequiresManualContextTermination at least once (sets an internal static flag), if no calls are made to this, the other methods are just dummies, and NetMQ works as is now, having zero impact on version 4.0 new way to work.

I do like the new contextless system, and use it outside Unity, it's just in the Unity Editor that there is need for some extra work on the NetMQ side.

dgsantana commented 8 years ago

For any one wanting to test this approach, I made it available here: [https://github.com/ycdivfx/netmq/tree/ManualContextTermination]

I also added some simple test and they pass, but they are simple. Sockets that aren't close, weren't tested yet.

somdoron commented 8 years ago

@dgsantana can you make a pull request?

PolynomialDivision commented 8 years ago

@dgsantana Thanks! This is working for me! I would like to see a pull request. :smile:

somdoron commented 8 years ago

I think it is already in... On Jun 24, 2016 14:31, "Polynomdivision" notifications@github.com wrote:

@dgsantana https://github.com/dgsantana Thanks! This is working for me! I would like to see a pull request. 😄

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/zeromq/netmq/issues/526#issuecomment-228322805, or mute the thread https://github.com/notifications/unsubscribe/AClv9vzoCkN-SfiHItsf8tfLUAtvJQz0ks5qO8AdgaJpZM4IHM7O .

dgsantana commented 8 years ago

Yeap it's in.

A Sex, 24 de jun de 2016, 12:54, Doron Somech notifications@github.com escreveu:

I think it is already in... On Jun 24, 2016 14:31, "Polynomdivision" notifications@github.com wrote:

@dgsantana https://github.com/dgsantana Thanks! This is working for me! I would like to see a pull request. 😄

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/zeromq/netmq/issues/526#issuecomment-228322805, or mute the thread < https://github.com/notifications/unsubscribe/AClv9vzoCkN-SfiHItsf8tfLUAtvJQz0ks5qO8AdgaJpZM4IHM7O

.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/zeromq/netmq/issues/526#issuecomment-228326926, or mute the thread https://github.com/notifications/unsubscribe/ACn3BMbn-MlrS3-vXdJI_pW8Ynr86uK_ks5qO8WEgaJpZM4IHM7O .

PolynomialDivision commented 8 years ago

Oh I thought it isn't in because of the open issue and there was no answer. Thank you! :)

YutaItoh commented 8 years ago

@dgsantana Following your test code, I tried the workaround on Unity3D (ver. 5.3.4f1, x64). Unfortunately, the issue still remains -- actually the Unity editor even gets stuck in the first run time.

A minimal code I wrote is the following:

// Attach this script on a GameObject in Unity3D and play in the editor
// --> the editor gets stuck at ContextTerminate() below
using UnityEngine;
using NetMQ; // for NetMQConfig
using NetMQ.Sockets; 

public class NetMQUnityTest: MonoBehaviour
{
    void Start()
    {
        NetMQConfig.ManualTerminationTakeOver();
        NetMQConfig.ContextCreate(true);

        using (var req = new RequestSocket())
        {
            req.Connect("tcp://127.0.0.1:50020");
            req.SendFrame("Hello");
            req.Close(); // testing with/without this line did not change the behavior.
        }

        // Unity editor gets stuck at this line
        NetMQConfig.ContextTerminate(); // giving 'true' as an arg. did not change the behavior.
    }
}

I suspect I'm misusing your utility functions, so I really appreciate if you can point out any faults in my test code...

I compiled NetMQ.dll and AsyncIO.dll from the master branch of NetMQ with VC2015, and placed in a Unity's asset folder.

PolynomialDivision commented 8 years ago

You still have to use

AsyncIO.ForceDotNet.Force();
YutaItoh commented 8 years ago

@PolynomialDivision Thank you! I totally forgot about that... As a reference for others, let me share a working code that'd be bit more practical for Unity use cases:

using UnityEngine;
using System.Threading;
using System.Collections;
using System.Timers;
using NetMQ; // for NetMQConfig
using NetMQ.Sockets; 

public class NetMQUnityTest: MonoBehaviour
{

    Thread client_thread_;
    private Object thisLock_ = new Object();
    bool stop_thread_ = false;

    void Start()
    {
        Debug.Log("Start a request thread.");
        client_thread_ = new Thread(NetMQClient);
        client_thread_.Start();
    }

    // Client thread which does not block Update()
    void NetMQClient()
    {
        AsyncIO.ForceDotNet.Force();
        NetMQConfig.ManualTerminationTakeOver();
        NetMQConfig.ContextCreate(true);

        string msg;
        var timeout = new System.TimeSpan(0, 0, 1); //1sec

        Debug.Log("Connect to the server.");
        var requestSocket = new RequestSocket(">tcp://192.168.11.36:50020");
        requestSocket.SendFrame("SUB_PORT");
        bool is_connected = requestSocket.TryReceiveFrameString(timeout, out msg);

        while (is_connected && stop_thread_ == false)
        {
            Debug.Log("Request a message.");
            requestSocket.SendFrame("msg");
            is_connected = requestSocket.TryReceiveFrameString(timeout, out msg);
            Debug.Log("Sleep");
            Thread.Sleep(1000);
        }

        requestSocket.Close();
        Debug.Log("ContextTerminate.");
        NetMQConfig.ContextTerminate();
    }

    void Update()
    {
        /// Do normal Unity stuff
    }

    void OnApplicationQuit()
    {
        lock (thisLock_)stop_thread_ = true;
        client_thread_.Join();
        Debug.Log("Quit the thread.");
    }

}

The above code does not freeze the editor after playing. It also doesn't block its Update function.

Borisss commented 8 years ago

@YutaItoh I was able to use your code with custom built NetMQ3.5 (from latest master), so thanks! I replaced obsolete methods with suggested ones.

How would I use netMQ if I need multiple sockets? Like getting messages from one address (1 instance of socket) and sending messages to a different address (X instances of sockets)? Unity (5.3.4f) gets stuck whenever there is more then one socket open (different monobehaviours) [exiting play mode], or while trying to use debugger :(.

Should I build from some old revision of netMQ master? Or is there some specific way how to treat Unity to avoid freezing?

Changes to above mentioned code:

protected override void NetMQClient() { AsyncIO.ForceDotNet.Force(); NetMQConfig.Cleanup(); ``` using (var server = new RouterSocket()) { server.Bind(connectPath); var timeout = new System.TimeSpan(0, 0, 1); //1sec NetMQMessage msg = new NetMQMessage(); while (!stop_thread_) { if (server.TryReceiveMultipartMessage(timeout, ref msg)) { Debug.Log("Received " + msg[1].ConvertToString()); } } server.Close(); NetMQConfig.Cleanup(); } } ```

Or is it possible to get somewhere the net35 compatible versions of AsyncIO.dll and NetMQ.dll (as it was mentioned above as important)? I'm not able to open AsyncIO sln for some reason in VS 2015 and so I don't know if it was resolved correctly by nuget while building NetMQ (I have no real experience with nuget).

PolynomialDivision commented 8 years ago

Why are you doing a NetMQConfig.Cleanup() at the beginning? Is this advisable? Maybe when you doing this you should use

NetMQConfig.Cleanup(true);

I had problems building the librarys with VS 2015, too. So I just installed the librarys in a clean VS Project with NuGet and then copied 35 libs to my unity project. This works fine. :)

As I unterstood it you should just make a cleanup in the end when you close the last socket.

Borisss commented 8 years ago

@PolynomialDivision I used the above code and as the method is obsolete replaced it with the suggestion:

[Obsolete("Use Cleanup method")] public static void ManualTerminationTakeOver();

Mystfit commented 8 years ago

I've been playing around with this issue for a bit and managed to trace the problem down a bit further.

So in my particular use case scenario, I'm mainly testing/debugging inside Unity's editor. I have more than one socket open and everything merrily connects and operates as expected. When I STOP the editor I start to call my cleanup code to close all my sockets/pollers and finish up with NetMQConfig.Cleanup(). When that is called, the editor will indefinitely hang, and I can see in the Windows Resource Monitor that the sockets are still open inside Unity. All of my sockets have linger set to 0.

After experimenting with a slightly earlier copy of NetMQ that allowed me to step through the debugger and figure out what was hanging, I noticed that the ProcessReaped() was never being called in the Reaper thread in response to a socket announcing its destruction.

Approaching from the opposite direction, I tracked the Socket destruction code to the ProcessTerm() method, and then up to the super method in the Own class. Inside the Own class's ProcessTerm() method (https://github.com/zeromq/netmq/blob/master/src/NetMQ/Core/Own.cs#L270), it iterates through each owned object and calls SendTerm() which results in a CommandType.Term message being dispatched. At this point, I couldn't see the command target ever receiving the term message and beginning the socket termination process. I'm unsure to why this is happening, and I wonder if the sockets are no longer processing command messages at this stage of the teardown for one reason or another due to how Unity is processing the NetMQ threads.

My workaround for this issue is to force-quit Unity and relaunch. My exported builds don't experience this issue as long as I drop NetMQConfig.Cleanup() and just let Windows dispose of everything when the exported Unity exits, but it's a bit of a frustrating solution.

mikaelhogstrom commented 8 years ago

I had some issues where unity would hang if scripts started rebuilding while I was playing but that was solved as described in this answer: https://answers.unity.com/questions/1246172/is-there-an-event-triggered-before-editor-starts-r.html

Supergeek commented 7 years ago

Using the latest Nuget version of the 35 libs in Unity 5.4.2p3, I'm still seeing the Unity editor lock up quite frequently. I made a very simple Dealer connection that works fine until I add a NetMQPoller into the mix. If I add that, the Unity editor locks up when I hit stop.

using (var client = new DealerSocket(">tcp://192.168.1.151:13151"))
//using (var poller = new NetMQPoller()) // uncomment this line to break Editor on stopping.
{
tobi-tobsen commented 7 years ago

@Supergeek from your pasted lines it is not clear if are you properly stopping / disposing

  1. the poller
  2. the sockets
  3. the context
Xitech1 commented 7 years ago

I know this is an old thread but for people running in the freeze problem after 1 time use.

The code @YutaItoh provided didn't work for me anymore. Maybe because my messages are fairly large. I've still used some of Yutaltoh's code so still thanks to him!

//Multithread for netMQ
    Thread client_thread_;
    private Object thisLock_ = new Object();
    bool stop_thread_ = false;

void NetMQClient()
    {
        AsyncIO.ForceDotNet.Force();
        NetMQConfig.Cleanup();

        string topic = "KV6XML";
        using (var subSocket = new SubscriberSocket())
        {
            subSocket.Options.ReceiveHighWatermark = 1000;
            subSocket.Connect("tcp://172.20.20.42:10100");
            subSocket.Subscribe(topic);
            Debug.Log("Subscriber socket connecting...");
            while (!stop_thread_)
            {
                Debug.Log("waiting...?");
                //   string messageTopicReceived = subSocket.ReceiveFrameString();
                //   Debug.Log(messageTopicReceived);
                string messageReceived = subSocket.ReceiveFrameString();
                Debug.Log(messageReceived);
            }
            subSocket.Disconnect("tcp://172.20.20.42:10100");
        }
        Debug.Log("ContextTerminate.");
        NetMQConfig.Cleanup();
    }

void OnApplicationQuit()
    {
        lock (thisLock_) stop_thread_ = true;
        client_thread_.Join();
        Debug.Log("Quit the thread.");

    }

Hope this helps some people. The only slight problem this has is that it'll require a next message in order to quite properly.

theladyjaye commented 7 years ago

I have the same issue, Unity 2017.1.1f1 (Win). The above did not resolve it.

It's not even the Second call to Play that locks it. Attempting to Quit Unity after running it once will still cause Unity to lock up.

EDIT

Ok.. well my problem with the above example was I was using a CancellationTokenSource and setting that to Cancel() when I switched to using the bool as in the example: bool stop_thread it works just fine.

MikeFair commented 7 years ago

As I recall, the problem was triggered by binding a listening socket; you could create Sockets that connected to other hosts okay, but could not receove them without causing the lock-up... It's been a while so I might be misremembering the exact causes (but I do remember that there were behaviors that would exit cleanly at the time). On Oct 9, 2017 10:37 AM, "Adam Venturella" notifications@github.com wrote:

I have the same issue, Unity 2017.1.1f1. The above did not resolve it.

It's not even the Second call to Play that locks it. Attempting to Quit Unity after running it once will still cause Unity to lock up.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/zeromq/netmq/issues/526#issuecomment-335228443, or mute the thread https://github.com/notifications/unsubscribe-auth/ACMqLbZT1I9nW_2CID8-7hKhjeBLqHIbks5sqlnKgaJpZM4IHM7O .

zoink47 commented 5 years ago

Had this issue with Unity 2018.3.12 with the editor being stuck at Begin Mono Manager Reload Assembly in the Editor.log.

I used this NuGet For Unity Utility to add this NetMQ.Unity package to my project instead of building from github source.

Adding NetMQConfig.Cleanup() fixed the issue for me. Took a while to track the problem down to this issue, so hopefully in the future it is easier to find with the reference to the Editor.log output.

TMPxyz commented 5 years ago

Here is a working REQ-REP helloworld code sample for unity2018.3.2 on Win10,

REP Server in Unity

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using NetMQ;
using NetMQ.Sockets;
using UnityEngine.Assertions;

namespace MH
{
    public class NMQRep : MonoBehaviour
    {
        public int _port = 7788;

        public ResponseSocket _server;

        void Start()
        {
            AsyncIO.ForceDotNet.Force();
            NetMQConfig.Linger = new TimeSpan(0,0,1);

            _server = new ResponseSocket();
            _server.Options.Linger = new TimeSpan(0,0,1);
            _server.Bind($"tcp://*:{_port}");
            print($"server on {_port}");

            Assert.IsNotNull(_server);

            StartCoroutine( _CoWorker() );
        }

        void OnDisable()
        {
            _server?.Dispose();
            NetMQConfig.Cleanup(false);
        }

        IEnumerator _CoWorker()
        {
            var wait = new WaitForSeconds(1f);

            while(true)
            {
                print("poll the recv...");
                if(_server.TryReceiveFrameString(out string recv) )
                {
                    print ($"server recv: {recv}");

                    _server.SendFrame("World");
                }
                else
                {
                    print ("no recv...");
                }

                yield return wait;
            }
        }

    }
}

REQ client in python:

import time
import zmq

ctx = zmq.Context()
soc = ctx.socket(zmq.REQ)
soc.setsockopt(zmq.LINGER, 1)
soc.connect("tcp://localhost:7788")
print("connected")

while True:
    soc.send_string("hello")
    print ("sent: 'hello'")
    s = soc.recv_string()
    print ( "recv: %s" % s)
TMPxyz commented 5 years ago

Also a REQ-REP with both client & server on Unity:

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using NetMQ;
using NetMQ.Sockets;
using UnityEngine.Assertions;

namespace MH
{
    ///<summary>
    /// test Req-Rep with NetMQ
    ///</summary>
    public class ReqRepNMQ : MonoBehaviour
    {
        public int _port = 7788;

        public RequestSocket _client;
        public ResponseSocket _server;

        public float _interval = 0.5f; // wait interval

        private float _timer = 0;
        private int _cnter = 1;

        void Start()
        {
            AsyncIO.ForceDotNet.Force();
            NetMQConfig.Linger = new TimeSpan(0,0,1);

            _server = new ResponseSocket();
            _server.Options.Linger = new TimeSpan(0,0,1);
            _server.Bind($"tcp://*:{_port}");
            print($"server on {_port}");

            _client = new RequestSocket();
            _client.Options.Linger = new TimeSpan(0,0,1);
            _client.Connect($"tcp://localhost:{_port}");
            print($"client connects {_port}");

            Assert.IsNotNull(_server);
            Assert.IsNotNull(_client);
        }

        void OnDisable()
        {
            _client?.Dispose();
            _server?.Dispose();
            NetMQConfig.Cleanup(false);
        }

        void Update()
        {
            _timer += Time.deltaTime;
            if( _timer >= _interval )
            {
                _timer = 0;
                var c_sent = $"Request {_cnter}";
                _client.SendFrame(c_sent);
                print($"client sents: {c_sent}");

                var s_recv = _server.ReceiveFrameString();
                print($"server receives {s_recv}");

                var s_sent = $"Response {_cnter}";
                _server.SendFrame(s_sent);
                print($"Server sents: {s_sent}");

                var c_recv = _client.ReceiveFrameString();
                print($"client receives {c_recv}");

                _cnter ++;
            }
        }
    }
}
stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had activity for 365 days. It will be closed if no further activity occurs within 56 days. Thank you for your contributions.