I'm not sure if this is the right subsite of stackexchange because it's not only about code review but a bit about design eihter.I'm currently developing a network application.I need to connect a (java) server with a tcp socket. I implemented two different variants of my client. One uses a blocking socket with threads, the other one uses a non blocking socket and Unitys Update method. Personally I like the one without threads better, but my concern is that if I use Unitys Update method writing to the socket could take longer, especially if Unitys framerate is low, since Update would be called less frequently than with a seperate thread. I know there are many other questions about blocking and non-blocking sockets, but nothing about Unity3d.The approach with a blocking TCPClient and Threads:using UnityEngine;using UnityEngine.Events;using System.Collections.Generic;using System.Net.Sockets;using System.Threading;public class ThreadedTestClient : MonoBehaviour{    public string Server = 127.0.0.1;    public int Port = 5001;    public int ReadBufferSize = 1024, IncomingBufferSize=1024*1024*4;    private byte[] ReadBuffer;    private TcpClient Connection;    private NetworkStream Stream;    private Queue<OutgoingMessage> WriteQueue;    private MessageBuffer IncomingBuffer;    private Thread Writer,Reader;    private bool Running;    void Start ()    {        try {            IncomingBuffer=new MessageBuffer(IncomingBufferSize);            ReadBuffer = new byte[ReadBufferSize];            WriteQueue = new Queue<OutgoingMessage> ();            Connection = new TcpClient();            Connection.Connect(Server,Port);            Stream=Connection.GetStream();            Running=true;            Writer=new Thread(Writing);            Writer.Start();            Reader=new Thread(Reading);            Reader.Start();            #if UNITY_EDITOR            UnityEditor.EditorApplication.playmodeStateChanged = delegate () {                if (!UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode &&                    UnityEditor.EditorApplication.isPlaying) {                    Debug.Log (string.Format([{0}] Exiting playmode.,GetType().Name));                    Running=false;                    Writer.Abort();                    Reader.Abort();                }            };            #endif        } catch (System.ArgumentNullException e) {            Debug.LogWarning (string.Format (ArgumentNullException: {0}, e));        } catch (SocketException e) {            Debug.LogWarning (string.Format (SocketException: {0}, e));        }    }    public void SendHelloWorld(){        string prefix=SechzehnSechzehn;//c# implementation of javas ByteBuffer        ByteBuffer b = ByteBuffer.allocate (1024);        byte[] content = System.Text.Encoding.UTF8.GetBytes (prefix+HelloWorld);        byte[] data = new byte[b.put (MessageBuffer.intToByteArray (content.Length)).put (content).flip ().limit ()];        b.get (data);        Write (data,()=>Debug.Log(Sended Hello World!));    }    public void SendRandomData(int size){        byte[] content = new byte[size+4];        new System.Random ().NextBytes (content);        byte[] bs=MessageBuffer.intToByteArray(size);        for (int i = 0; i < bs.Length; i++) {            content [i] = bs [i];        }        Write (content,()=>Debug.Log(Sended Random data!));    }    //onDone doesnt guarantee any data to have reached to server, just asures that data where passed to the underlying socket    public void Write (byte[] b,UnityAction onDone)    {        WriteQueue.Enqueue (new OutgoingMessage(b,onDone));    }    private void CallWorker(Queue<MessageBuffer.EncryptedMessage> messages){        //TODO    }    private void Reading ()    {        while (Running & Connection.Connected) {                int readed = Stream.Read (ReadBuffer, 0, ReadBufferSize);                //addFrom returns the amount of complete messages;                if (IncomingBuffer.addFrom (ReadBuffer, 0, readed) > 0) {                    //gets the queue of complete messages that arrived                    CallWorker (IncomingBuffer.getAndResetQueue ());                }        }    }    private void Writing(){        while (Running & Connection.Connected) {            if (WriteQueue.Count > 0) {                OutgoingMessage packet = WriteQueue.Dequeue();                Stream.Write (packet.Data, 0, packet.Data.Length);                packet.Done ();            }        }    }    private class OutgoingMessage{        private readonly UnityAction OnDone;        public readonly byte[] Data;        public OutgoingMessage(byte[] data, UnityAction onDone){            Data=data;            OnDone=onDone;        }        public void Done(){            if (OnDone != null) {                OnDone ();            }        }    }}The approach with a non-blocking TCPClient and Unitys Update:using UnityEngine;using UnityEngine.Events;using System.Collections.Generic;using System.Net.Sockets;public class TestClient : MonoBehaviour{    public string Server = 127.0.0.1;    public int Port = 5001;    public int ReadBufferSize = 1024, IncomingBufferSize=1024*1024*4;    private byte[] ReadBuffer;    private TcpClient Connection;    private Queue<OutgoingMessage> WriteQueue;    private int WriteOffset;    private MessageBuffer IncomingBuffer;    void Start ()    {        try {            IncomingBuffer=new MessageBuffer(IncomingBufferSize);            ReadBuffer = new byte[ReadBufferSize];            WriteQueue = new Queue<OutgoingMessage> ();            Connection = new TcpClient();            Connection.Connect(Server,Port);            Connection.Client.Blocking = false;        } catch (System.ArgumentNullException e) {            Debug.LogWarning (string.Format (ArgumentNullException: {0}, e));        } catch (SocketException e) {            Debug.LogWarning (string.Format (SocketException: {0}, e));        }    }    public void SendHelloWorld(){        string prefix=SechzehnSechzehn;        ByteBuffer b = ByteBuffer.allocate (1024);        byte[] content = System.Text.Encoding.UTF8.GetBytes (prefix+HelloWorld);        byte[] data = new byte[b.put (MessageBuffer.intToByteArray (content.Length)).put (content).flip ().limit ()];        b.get (data);        Write (data,()=>Debug.Log(Sended Hello World!));    }    public void SendRandomData(int size){        byte[] content = new byte[size+4];        new System.Random ().NextBytes (content);        byte[] bs=MessageBuffer.intToByteArray(size);        for (int i = 0; i < bs.Length; i++) {            content [i] = bs [i];        }        Write (content,()=>Debug.Log(Sended Random data!));    }    public void Write (byte[] b,UnityAction onDone)    {        WriteQueue.Enqueue (new OutgoingMessage(b,onDone));    }    private void CallWorker(Queue<MessageBuffer.EncryptedMessage> messages){        //TODO    }    void Update ()    {        if (Connection.Connected) {            if (Connection.Client.Available > 0) {                int readed=Connection.Client.Receive (ReadBuffer);                if (IncomingBuffer.addFrom (ReadBuffer, 0, readed) > 0) {                    CallWorker (IncomingBuffer.getAndResetQueue ());                }            }            if (WriteQueue.Count > 0) {                OutgoingMessage packet = WriteQueue.Peek ();                WriteOffset += Connection.Client.Send (packet.Data, WriteOffset, packet.Data.Length - WriteOffset, SocketFlags.None);                if (WriteOffset >= packet.Data.Length) {                    WriteQueue.Dequeue ();                    WriteOffset = 0;                    packet.Done ();                }            }        }    }    private class OutgoingMessage{        private readonly UnityAction OnDone;        public readonly byte[] Data;        public OutgoingMessage(byte[] data, UnityAction onDone){            Data=data;            OnDone=onDone;        }        public void Done(){            if (OnDone != null) {                OnDone ();            }        }    }}
Blocking TCP Client with Threads vs. Non-Blocking TCP Client with Unitys Update
c#;multithreading;networking;socket;unity3d