Simplest code to connect over TCP ip from unity to telnet

Hi,

I’m currently developing a motion capture solution to capture upper body movement using inertial sensors.
The hardware part can deliver the euler angles data direcly over a tcp/ip connection to any device asking for it on the network, but now I try to make unity connect to it.

On the wiki I found the following code.

using UnityEngine;

using System.Collections;
using System.Net.Sockets;
using System.Net;

public class Client : MonoBehaviour {
    
    public string m_IPAdress = "127.0.0.1";
    public const int kPort = 10253;

    private static Client singleton;

    
    private Socket m_Socket;
    void Awake ()
    {
        m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        // System.Net.PHostEntry ipHostInfo = Dns.Resolve("host.contoso.com");
        // System.Net.IPAddress remoteIPAddress = ipHostInfo.AddressList[0];
        System.Net.IPAddress    remoteIPAddress  = System.Net.IPAddress.Parse(m_IPAdress);
        
        System.Net.IPEndPoint   remoteEndPoint = new System.Net.IPEndPoint(remoteIPAddress, kPort);

        singleton = this;
        m_Socket.Connect(remoteEndPoint);
    }
    
    void OnApplicationQuit ()
    {
        m_Socket.Close();
        m_Socket = null;
    }
    
    static public void Send(MessageData msgData)
    {
        if (singleton.m_Socket == null)
            return;
            
        byte[] sendData = MessageData.ToByteArray(msgData);
        byte[] prefix = new byte[1];
        prefix[0] = (byte)sendData.Length;
        singleton.m_Socket.Send(prefix);
        singleton.m_Socket.Send(sendData);
    }


}

Now I see that the send function expects a MessageData object. Does anyone in here know how I could create a SEND function which accepts a simple string variable ?

And any idea how to check if there is data available from the server and then read it in as a string (or maybe as an array of byte, that doesn’t matter too much)?

Any help/hints would be highly appreciated since this is a very simple connection but I need to make it very robust because it will need to send quite some data from the hardware to unity.

Kind regards,

Bart

untested but this should work i think :

    static public void Send(string msgData)
    {
        if (singleton.m_Socket == null)
            return;

	System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
        byte[] sendData = encoding.GetBytes(msgData);
        byte[] prefix = new byte[1];
        prefix[0] = (byte)sendData.Length;
        singleton.m_Socket.Send(prefix);
        singleton.m_Socket.Send(sendData);
    }

if it doesn’t work you should have a look on microsoft’s site on sockets in .net 2.0
http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.aspx#Y6100

Thank you.

Would you also have an idea how I can read data from my connection?

In flash we do this by ataching an event handler in code, but I suppose in unity this is not the way to do it and I’ll have to POLL for incoming data in every Update() cycle? Any hints on that?

Kind regards,

Bart

yes, you would do something like this in the update function :

bytes = s.Receive(bytesReceived, bytesReceived.Length, 0);

s refers to the socket
and then decode the bytes to a string

so bytesReceived would contain the bytes received. What data type would this bytesReceived be?

And bytesReceived.Length is the amount of bytes received, but it this a value which I have to enter somewhere or is it done in such a way that when I call this Receive method on my socket, the bytesReceived.length is auto-filled?

I found in the .net docs that there a quite a lot of overloaded Receive methods available

the data is of type byte[ ]
then decode like this :

System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
string sendData = encoding.GetString(bytesReceived);

Hmmm, still troubles.

I tried the code below

Now I’m 100% sure that my unity program does connect to port 5333 on localhost and that server listening on port 5333 does send data to unity.

However, I thought that I would see information received in the GUIlabel, but it shows absolutely nothing.

Anyone have an idea what I do wrong?

Kind regards,

Bart

yeah that won’t work.

void Update () {
bytes = m_Socket.Receive(bytesReceived, bytesReceived.Length, 0);	
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
sendData = encoding.GetString(bytesReceived);	
}

it should be in the lines of :

void Update () {
bytes = m_Socket.Receive(bytesReceived, bytesReceived.Length, 0);	
while(bytes != null)
{
    System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
    string receivedData = encoding.GetString(bytes);
}
}

then your receivedData is your received text

The problem persists.

My latest version of the code is now

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


public class Client : MonoBehaviour {
	
	public string m_IPAdress = "127.0.0.1";
    public const int kPort = 5333;
	public int bytes;
    private Socket m_Socket;
	public byte[] bytesReceived;
	public string receivedData="";

	void Awake(){
		m_Socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
		System.Net.IPAddress    remoteIPAddress  = System.Net.IPAddress.Parse(m_IPAdress);
        System.Net.IPEndPoint   remoteEndPoint = new System.Net.IPEndPoint(remoteIPAddress, kPort);
        m_Socket.Connect(remoteEndPoint);
	}
	
	void Update () {
		bytes = m_Socket.Receive(bytesReceived, bytesReceived.Length, 0);
		while(bytes != 0)
		{
    		System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
    		string receivedData = encoding.GetString(bytesReceived);
		}
	}	
	
	    void OnApplicationQuit ()
    {
        m_Socket.Close();
        m_Socket = null;
    }
	
	void OnGUI() {
     GUI.Label(new Rect(0, 40, 1000, 400), receivedData);
}
}

And somehow it doesn’t receive data.
If I look at the value of variable bytes, then its always 0, so maybe something is still terribly wrong in my code?

The tcp server does show that my client program connected and the server is absolutely surely sending data.

Any idea what could be wrong here?

By the way, I had to change 1 line to while(bytes != 0) because if I used while(bytes != null) then unity goes into infinite loop and hangs.

sent you a pm

Hey, I’m also using an arduino to send data, I can’t use serial as I’m on mac and mono shoots errors, but I was hoping I can send data from the arduino with ethernet shield in the meantime. Did you ever get this working? I would really appreciate the help.

@educasoft,

you should not use blocking communication. The best way is to use threading (System.Threading) and callback to ensure you will read/write to the TCP buffer without blocking your Unity application.

I currently am not working on this, but here is the script which worked. There is too much code in that script but you can isolate the networking specific stuff I guess

using UnityEngine;

using System.Collections;

using System;

using System.IO;

using System.Net.Sockets;

//using System.Globalization.NumberStyles;



public class Sockesfleximan : MonoBehaviour

{

	public string tekst;

	public float rotatieX;

	public float rotatieY;

	public float rotatieZ;

	public Transform nek;

	

	

	public byte[] bytesX = new byte[4];

	public byte[] bytesY = new byte[4];

	public byte[] bytesZ = new byte[4];

	public byte[] bytesW = new byte[4];

	

	public float xValue= (float)0.0;

	public float yValue= (float)0.0;

	public float zValue= (float)0.0;



	

	public Quaternion rot=Quaternion.identity;

	public Quaternion sensor=Quaternion.identity;



	

	public float[] qq = new float[4];

	

    internal Boolean socketReady = false;

    TcpClient mySocket;

    NetworkStream theStream;

    StreamWriter theWriter;

    StreamReader theReader;

    String Host = "localhost";

    Int32 Port = 5333;

	

	void Update()

    {

	   string receivedText = readSocket();

		if (receivedText != "")

        {

		tekst=receivedText;

			

		bytesX[0]=(byte)(HexToByte(tekst.Substring(0,1))*16+HexToByte(tekst.Substring(1,1)));

		bytesX[1]=(byte)(HexToByte(tekst.Substring(2,1))*16+HexToByte(tekst.Substring(3,1)));

		bytesX[2]=(byte)(HexToByte(tekst.Substring(4,1))*16+HexToByte(tekst.Substring(5,1)));

		bytesX[3]=(byte)(HexToByte(tekst.Substring(6,1))*16+HexToByte(tekst.Substring(7,1)));

		bytesY[0]=(byte)(HexToByte(tekst.Substring(8,1))*16+HexToByte(tekst.Substring(9,1)));

		bytesY[1]=(byte)(HexToByte(tekst.Substring(10,1))*16+HexToByte(tekst.Substring(11,1)));

		bytesY[2]=(byte)(HexToByte(tekst.Substring(12,1))*16+HexToByte(tekst.Substring(13,1)));

		bytesY[3]=(byte)(HexToByte(tekst.Substring(14,1))*16+HexToByte(tekst.Substring(15,1)));

		bytesZ[0]=(byte)(HexToByte(tekst.Substring(16,1))*16+HexToByte(tekst.Substring(17,1)));

		bytesZ[1]=(byte)(HexToByte(tekst.Substring(18,1))*16+HexToByte(tekst.Substring(19,1)));

		bytesZ[2]=(byte)(HexToByte(tekst.Substring(20,1))*16+HexToByte(tekst.Substring(21,1)));

		bytesZ[3]=(byte)(HexToByte(tekst.Substring(22,1))*16+HexToByte(tekst.Substring(23,1)));

		bytesW[0]=(byte)(HexToByte(tekst.Substring(24,1))*16+HexToByte(tekst.Substring(25,1)));

		bytesW[1]=(byte)(HexToByte(tekst.Substring(26,1))*16+HexToByte(tekst.Substring(27,1)));

		bytesW[2]=(byte)(HexToByte(tekst.Substring(28,1))*16+HexToByte(tekst.Substring(29,1)));

		bytesW[3]=(byte)(HexToByte(tekst.Substring(30,1))*16+HexToByte(tekst.Substring(31,1)));

			

		sensor.x=System.BitConverter.ToSingle( bytesX, 0);	

		sensor.y=System.BitConverter.ToSingle( bytesY, 0);	

		sensor.z=System.BitConverter.ToSingle( bytesZ, 0);	

		sensor.w=System.BitConverter.ToSingle( bytesW, 0);	



		qq[0]=System.BitConverter.ToSingle( bytesX, 0);	

		qq[1]=System.BitConverter.ToSingle( bytesY, 0);	

		qq[2]=System.BitConverter.ToSingle( bytesZ, 0);	

		qq[3]=System.BitConverter.ToSingle( bytesW, 0);	



		rotatieX=sensor.eulerAngles.x;

		rotatieY=sensor.eulerAngles.y;

		rotatieZ=sensor.eulerAngles.z;

			

			

			

//		rot.x=sensor.x;

//		rot.y=sensor.y;

//		rot.z=sensor.z;

//		rot.w=sensor.w;

			

		rot.x=-qq[1];

		rot.y=qq[0];

		rot.z=-qq[2];

		rot.w=qq[3];

			

		rot *= Quaternion.Euler(Vector3.up * yValue);

		rot *= Quaternion.Euler(Vector3.right * xValue);

		rot *= Quaternion.Euler(Vector3.forward * zValue);

			

			

			

 	//rot *= Quaternion.Euler(Vector3(90,90,90));

			

			

		nek.rotation=rot;

		//nek.rotation=Quaternion.Euler(-rotatieY,rotatieX,-rotatieZ);

        }

    }



    void OnGUI()

    {

		

		if (!socketReady)

		{	

         if (GUILayout.Button("Connect"))

         {

             setupSocket();

             writeSocket("serverStatus:");

         }

		}



       // if (GUILayout.Button("Send"))

       // {

       //     writeSocket("test string");

       // }



       // if (GUILayout.Button("Close"))

       // {

       //     closeSocket();

       // }

		

		//GUI.Label(new Rect(0, 40, 1000, 400), tekst);

		if (socketReady)

		{	

         xValue = GUI.HorizontalSlider (new Rect (25, 25, 360, 30), (float)xValue, 180.0f, -180.0f);

         yValue = GUI.HorizontalSlider (new Rect (25, 50, 360, 30), (float)yValue, 180.0f, -180.0f);

         zValue = GUI.HorizontalSlider (new Rect (25, 75, 360, 30), (float)zValue, 180.0f, -180.0f);

		}

		

    }



    void OnApplicationQuit()

    {

        closeSocket();

    }



    public void setupSocket()

    {

        try

        {

            mySocket = new TcpClient(Host, Port);

            theStream = mySocket.GetStream();

            theWriter = new StreamWriter(theStream);

            theReader = new StreamReader(theStream);

            socketReady = true;

        }



        catch (Exception e)

        {

            Debug.Log("Socket error: " + e);

        }

    }



    public void writeSocket(string theLine)

    {

        if (!socketReady)

            return;

        String foo = theLine + "\r\n";

        theWriter.Write(foo);

        theWriter.Flush();

    }



    public String readSocket()

    {

        if (!socketReady)

            return "";

        if (theStream.DataAvailable)

            return theReader.ReadLine();

			//return theReader.ReadToEnd();

        return "";

    }



    public void closeSocket()

    {

        if (!socketReady)

            return;

        theWriter.Close();

        theReader.Close();

        mySocket.Close();

        socketReady = false;

    }



	private byte HexToByte(string hexVal)

	{

		if (hexVal=="0") return (0);

		else if (hexVal=="1") return (1);

		else if (hexVal=="2") return (2);

		else if (hexVal=="3") return (3);

		else if (hexVal=="4") return (4);

		else if (hexVal=="5") return (5);

		else if (hexVal=="6") return (6);

		else if (hexVal=="7") return (7);

		else if (hexVal=="8") return (8);

		else if (hexVal=="9") return (9);

		else if (hexVal=="A") return (10);

		else if (hexVal=="B") return (11);

		else if (hexVal=="C") return (12);

		else if (hexVal=="D") return (13);

		else if (hexVal=="E") return (14);

		else if (hexVal=="F") return (15);

		else return (0);

	}

}

Could you add the brackets please? ;)

Of course, didn’t notice I hadn’t done it :slight_smile:

Thanks! :slight_smile:

how can i change the int32 port into String?
cause i need to make it user input for the port.
thank you

Try Google sometime, saves you alot of time:
http://msdn.microsoft.com/en-us/library/system.object.tostring.aspx

Are you using the C# Telnet protocol?
http://stackoverflow.com/questions/390188/c-sharp-telnet-library