简体   繁体   中英

AsyncTCP C# - arduino/unity communication

I've been working the last weeks with a tcp protocol to send packet from arduino to unity using this code:

using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;

public class TCPConnection : MonoBehaviour
{
    public string IP_Seat = "192.168.137.161";  
    public int port = 34197;
    #region private members     
    private TcpClient socketConnection;
    private Thread clientReceiveThread;
    public float a, b, c, vel;
    public float test = 0.0f;
    #endregion
    // Use this for initialization  
    void Awake()
    {
        ConnectToTcpServer();
    }
    
    /// <summary>   
    /// Setup socket connection.    
    /// </summary>  
    private void ConnectToTcpServer()
    {
        try
        {
            clientReceiveThread = new Thread(new ThreadStart(ListenForData));
            clientReceiveThread.IsBackground = true;
            clientReceiveThread.Start();
        }
        catch (Exception e)
        {
            Debug.Log("On client connect exception " + e);
        }
    }
    /// <summary>   
    /// Runs in background clientReceiveThread; Listens for incomming data.     
    /// </summary>     
    private void ListenForData()
    {
        var aold = 0.0f;
        var bold = 0.0f;
        var cold = 0.0f;
        var velold = 0.0f;
        try
        {
            socketConnection = new TcpClient(IP_Seat, port);
            //cketConnection.ConnectAsync(IP_Seat, port);  // non si connette
            //socketConnection.Client.Blocking = false;
            //socketConnection.Client.ConnectAsync(IP_Seat,port);
            Byte[] bytes = new Byte[16];
            while (socketConnection.Connected)
            {
                // Get a stream object for reading              
                using (NetworkStream stream = socketConnection.GetStream())
                {
                    int length;
                    // Read incomming stream into byte arrary.                  
                    while ((length = stream.Read(bytes, 0, bytes.Length)) != 0)
                    {
                        //Debug.Log("I'm receiving Data");
                        if (length == 16)
                        {
                            //Debug.Log("I'm receiving len 16 and I like it");
                            var incommingData = new byte[length];
                            var A = new Byte[4];
                            var B = new Byte[4];
                            var C = new Byte[4];
                            var VEL = new Byte[4];

                            Array.Copy(bytes, 0, incommingData, 0, length);
                            // Convert byte array to string message.                        
                            string serverMessage = Encoding.ASCII.GetString(incommingData);
                             Array.Copy(bytes, 0, A, 0, 4);
                             Array.Copy(bytes, 4, B, 0, 4);
                             Array.Copy(bytes, 8, C, 0, 4);
                             Array.Copy(bytes, 12, VEL, 0, 4);



                            a = BitConverter.ToSingle(A, 0) < 0 ? BitConverter.ToSingle(A, 0) : aold;
                            b = BitConverter.ToSingle(B, 0) < 0 ? BitConverter.ToSingle(B, 0) : bold;
                            c = BitConverter.ToSingle(C, 0) < 0 ? BitConverter.ToSingle(C, 0) : cold;
                            vel = BitConverter.ToSingle(VEL, 0); //< 0 ? BitConverter.ToSingle(C, 0) : 0;

                            //Debug.Log("server message received as: " + serverMessage +a +" "+b + " " + c + " " + vel);

                            aold = a;
                            bold = b;
                            cold = c;
                            velold = vel;

                        }
                        else {
                            //evitare che bilancia aspetti ack di tcp
                        }
                    }

                }
            }
        }
        catch (SocketException socketException)
        {
            Debug.Log("Socket exception: " + socketException);
        }
    }

}

and right now i'm having blocking issues: i'd like to use the async method for the TCP but the tcpClient.ConnectAsync but it returns a SocketEXception and I can't figure out why.

The arduino sends 4 float in 16 bytes packet and 98-99% of them arrive correctly, but the missing 1-2% causes the system to block and an undesirable behaviour ( since i'm programming a device I need no delay waiting for an ack or a packet)

How can I make this sokcet async?

As @jdweng already said: TCP is just an undefined stream of data you need to implement an according protocol for knowing when a message ends (is fully received) and when a new one starts.

Now in your case you seem to already know that you have exactly 16 bytes.

Not the other parameter of NetworkStream.Read which is

int offset -> The location in buffer to begin storing the data to.

what you want to do is wait until the buffer is actually full like

var receivedBytes = 0;
while (receivedBytes < bytes.Length)
{
    receivedBytes +=  stream.Read(bytes, receivedBytes, bytes.Length - receivedBytes);
}

// Use bytes

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM