Sir
Sir

Reputation: 8280

How to stop my program from freezing up with TCP connection C#

I have created a TCP client and it connects fine but am a bit confused how to receive messages from the server without closing the connection ?

My current approach was to run a co-routine over the network stream read method but that freezes my program up so its obviously the wrong approach so am not sure how to fix it.

I want to keep the connection alive and read messages when ever they may arrive from the server.

This is what i have setup currently:

// the idea is to run a coroutine for recieving messages
private IEnumerator<float> _RunTCPSocket()
{
    int timer = DateTime.Now.Second;
    byte[] readBuffer = new byte[1024];

    while (SocketManager.IsConnected)
    {
        // this is the keep alive packets to server to prevent timeout on server side
        if (DateTime.Now.Second - timer > KeepAliveRate)
        {
            Debug.Log("Sending");
            timer = DateTime.Now.Second;
            SocketManager.Send(null);
        }

        int msgLength = SocketManager.Recieve(readBuffer); 
        if (msgLength > 0)
            Debug.Log(Encoding.ASCII.GetString(readBuffer, 0, msgLength));

        yield return Timing.WaitForOneFrame;
    }
}

This is the code for the receive method:

    public int Recieve(byte[] readBuffer)
    {
        if (!IsConnected)
            return -1; //-1 signifies an error aka we are disconnected

        try
        {
            // NetworkStream is from TcpClient.GetStream()
            bytesRead = _networkStream.Read(readBuffer, 0, readBuffer.Length);
        }
        catch (Exception e)
        {
            IsConnected = false;
            Debug.Log(e);
            bytesRead = -1;
        }

        return bytesRead;
    }

How do i prevent this from locking up my program ?

Upvotes: 1

Views: 1267

Answers (1)

Sy Le
Sy Le

Reputation: 163

You can use Begin/End method to make your program responsible:

Document from microsoft

You can see that the using of BeginReceive method is so complex so personally, i don't think it's easy to use.
An alternative is to call the read/write method inside a Task.
The third option is use TcpClient which used on client side and TcpListener which used on server side. Those two class is just a wrapper for an underline TCP socket. Those wrapper can make your life much more easier with Stream and Async methods.

If you want to learn more about network programming with C#, i highly recomment this book:
C# Network Programming by Richard Blum

Update

Code for working with Task:

    public event EventHandler<ReceiveDataEventArgs> DataReceived = null;
    public void StartReceive()
    {
        Task.Run(() =>
        {
            while (true)
            {
                var bytesRead = _networkStream.Read(readBuffer, 0, readBuffer.Length);
                DataReceived?.Invoke(this, new ReceiveDataEventArgs
                {
                    Data = bytesRead
                });
            }
        });

    }

    public class ReceiveDataEventArgs : EventArgs
    {
        public byte[] Data { get; set; }
    }

Upvotes: 1

Related Questions