simple udp implementation (send/read via mono/c#)

Two Objects for send and receiving UDP-Packets. Hope this helps. Updated code you will find (german) on our university gamedevelopment page:

http://www.gametheory.ch/index.jsp?positionId=101139&displayOption=

la1n


UDPReceive.cs

/*

	-----------------------
	UDP-Receive (send to)
	-----------------------
	// [url]http://msdn.microsoft.com/de-de/library/bb979228.aspx#ID0E3BAC[/url]
	
	
	// > receive 
	// 127.0.0.1 : 8051
	
	// send
	// nc -u 127.0.0.1 8051

*/
using UnityEngine;
using System.Collections;

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;

public class UDPReceive : MonoBehaviour {
    
    // receiving Thread
    Thread receiveThread; 

	// udpclient object
	UdpClient client; 

	// public
	// public string IP = "127.0.0.1"; default local
    public int port; // define > init

	// infos
	public string lastReceivedUDPPacket="";
	public string allReceivedUDPPackets=""; // clean up this from time to time!
	
	
	// start from shell
    private static void Main() 
    {
       UDPReceive receiveObj=new UDPReceive();
       receiveObj.init();

		string text="";
		do
		{
			 text = Console.ReadLine();
		}
		while(!text.Equals("exit"));
    }
    // start from unity3d
    public void Start()
    {
    	
    	init();	
    }
    
    // OnGUI
    void OnGUI()
	{
		Rect rectObj=new Rect(40,10,200,400);
			GUIStyle style = new GUIStyle();
				style.alignment = TextAnchor.UpperLeft;
		GUI.Box(rectObj,"# UDPReceive\n127.0.0.1 "+port+" #\n"
					+ "shell> nc -u 127.0.0.1 : "+port+" \n"
					+ "\nLast Packet: \n"+ lastReceivedUDPPacket
					+ "\n\nAll Messages: \n"+allReceivedUDPPackets
				,style);
	}
	    
    // init
    private void init()
    {
    	// Endpunkt definieren, von dem die Nachrichten gesendet werden.
        print("UDPSend.init()");
        
        // define port
        port = 8051;

        // status
        print("Sending to 127.0.0.1 : "+port);
        print("Test-Sending to this Port: nc -u 127.0.0.1  "+port+"");
 
    
    	// ----------------------------
		// Abhören
		// ----------------------------
        // Lokalen Endpunkt definieren (wo Nachrichten empfangen werden).
        // Einen neuen Thread fĂĽr den Empfang eingehender Nachrichten erstellen.
        receiveThread = new Thread(
            new ThreadStart(ReceiveData));
        receiveThread.IsBackground = true;
        receiveThread.Start();
 
    }

	// receive thread 
    private  void ReceiveData() 
    {

        client = new UdpClient(port);
        while (true) 
        {

            try 
            {
                // Bytes empfangen.
                IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
                byte[] data = client.Receive(ref anyIP);

                // Bytes mit der UTF8-Kodierung in das Textformat kodieren.
                string text = Encoding.UTF8.GetString(data);

                // Den abgerufenen Text anzeigen.
                print(">> " + text);
                
                // latest UDPpacket
                lastReceivedUDPPacket=text;
                
                // ....
                allReceivedUDPPackets=allReceivedUDPPackets+text;
                
            }
            catch (Exception err) 
            {
                print(err.ToString());
            }
        }
    }
    
    // getLatestUDPPacket
    // cleans up the rest
    public string getLatestUDPPacket()
    {
    	allReceivedUDPPackets="";
    	return lastReceivedUDPPacket;
    }
}

UDPSend.cs

/*

	-----------------------
	UDP-Send
	-----------------------
	// [url]http://msdn.microsoft.com/de-de/library/bb979228.aspx#ID0E3BAC[/url]
	
	// > gesendetes unter 
	// 127.0.0.1 : 8050 empfangen
	
	// nc -lu 127.0.0.1 8050

        // todo: shutdown thread at the end
*/
using UnityEngine;
using System.Collections;

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;

public class UDPSend : MonoBehaviour
{
    private static int localPort;
    
    // prefs 
    private string IP;  // define in init
	public int port;  // define in init
    
    // "connection" things
    IPEndPoint remoteEndPoint;
    UdpClient client;
    
    // gui
	string strMessage="";
	
        
    // call it from shell (as program)
    private static void Main() 
    {
    	UDPSend sendObj=new UDPSend();
    	sendObj.init();
    	
    	// testing via console
    	// sendObj.inputFromConsole();
    	
    	// as server sending endless
    	sendObj.sendEndless(" endless infos \n");
    	
    }
	// start from unity3d
	public void Start()
	{
		init();	
	}
	
	// OnGUI
    void OnGUI()
	{
		Rect rectObj=new Rect(40,380,200,400);
			GUIStyle style = new GUIStyle();
				style.alignment = TextAnchor.UpperLeft;
		GUI.Box(rectObj,"# UDPSend-Data\n127.0.0.1 "+port+" #\n"
					+ "shell> nc -lu 127.0.0.1  "+port+" \n"
				,style);
		
		// ------------------------
		// send it
		// ------------------------
		strMessage=GUI.TextField(new Rect(40,420,140,20),strMessage);
		if (GUI.Button(new Rect(190,420,40,20),"send"))
		{
			sendString(strMessage+"\n");
		}		
	}
    
	// init
	public void init()
	{
		// Endpunkt definieren, von dem die Nachrichten gesendet werden.
        print("UDPSend.init()");
        
        // define
        IP="127.0.0.1";
 		port=8051;
 		
		// ----------------------------
		// Senden
		// ----------------------------
        remoteEndPoint = new IPEndPoint(IPAddress.Parse(IP), port);
        client = new UdpClient();
        
        // status
        print("Sending to "+IP+" : "+port);
        print("Testing: nc -lu "+IP+" : "+port);
	
	}

	// inputFromConsole
    private void inputFromConsole()
    {
    	try 
        {
            string text;
            do 
            {
                text = Console.ReadLine();

                // Den Text zum Remote-Client senden.
                if (text != "") 
                {

                    // Daten mit der UTF8-Kodierung in das Binärformat kodieren.
                    byte[] data = Encoding.UTF8.GetBytes(text);

                    // Den Text zum Remote-Client senden.
                    client.Send(data, data.Length, remoteEndPoint);
                }
            } while (text != "");
        }
        catch (Exception err)
        {
            print(err.ToString());
        }

    }

    // sendData
    private void sendString(string message)
    {
    	try 
        {
                //if (message != "") 
                //{

                    // Daten mit der UTF8-Kodierung in das Binärformat kodieren.
                    byte[] data = Encoding.UTF8.GetBytes(message);

                    // Den message zum Remote-Client senden.
                    client.Send(data, data.Length, remoteEndPoint);
                //}
        }
        catch (Exception err)
        {
            print(err.ToString());
        }
    }
   
   
    // endless test
    private void sendEndless(string testStr)
    {
    	do
    	{
    		sendString(testStr);
    		
    		
    	}
    	while(true);
    	
    }
    
}
2 Likes

Thanks for sharing :slight_smile:
Have you added it to the wiki yet?

but can do it as soon as i find the time for it .-)

This is nice thanks.

One thing, I think the thread and client should be disabled on OnDisable() function.

void OnDisable()
{
if ( receiveThread!= null)
receiveThread.Abort();

client.Close();
}

Which next time it starts in game doesn’t cause crash.

1 Like

Thanks for sharing!

Thank you for sharing the codes. I have added them to the project.
But not sure how to use them.

Can some one help me with this?

Many thanks!

la1n:
Thank you fpr sharing the code!

tigerspidey123:
Thank you for fixing the crashing problem. (Do we need to insert your addendum to both sender and receiver?)

-Adamo

Nice, thanks! Does this work with iOS basic? I’m still not sure if it supports TCP/UDP :m

Very useful code indeed! Thanks for sharing!

Among other things, this was quite useful for quickly implementing that 6dofstreamer socket streamer for FaceAPI, just for the kicks of testing it :slight_smile:

Thanks!

When you write:

Does this mean that you use C# to start the a new process from a script run in unity?!?:

Process myProc = new Process();
myProc.StartInfo.FileName = "c:\MyApp\startProgram";
myProc.Start();

or how is this called?

right it starts a new process (“application”) that runs on its own side by side to it

What if you want to send data outside the LAN? I guess these scripts won’t work?

I have two questions:

I ran your example in Unity and I get an error:

UnityEngine.Object:ToString()
UDPReceive:ReceiveData() (at Assets/_Common/_Scripts/_Model/UDPReceive.cs:144)

It says something about Unity not liking when ToString is called in a thread outside of the main thread.

Also, I need some clarification on something.

IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
byte[ ] data = client.Receive(ref anyIP);

Looking at these two lines of code you are receiving packets from any IP address sent on any port? Or are you receiving packets from any IP address sent on the port that the client was initialized on? Shouldn’t you specify the exact IP address and/or port the end point is sending packets from?

All in all I was just wondering why most examples I see: IPEndPoint(IPAddress.Any, 0) instead of IPEndPoint(IPAddress.parse(“127.0.0.1”), 8051)?

Thanks

I want to send UDP packet to remote server, then how to? I tried change the IP and port of default(127.0.0.1, 8051) to specific server’s like (95.212.8.10, 4030), but then, this script’s sending function does not work.

Where and how must be revised for use with remote master server?

is the remote server or more specifically its firewall and router configured for it? UDP packets, when they are not correctly forwarded by the hardware etc are just dropped.

thats not the problem. but the server / machine you send it too must be reachable and have port forwarded.

thats nothing that has to do with your code but the network setup.

also if this ip is your own it might fail just by definition as not all routers are able to backroute such things

1 Like

Hello,

I’m using a modified version of this UDPClient script to receive messages from LabView. Everything works smoothly until I stop the game at Unity before ending the LabView program which is sending the UDP data. By doing this, I get the following message:

System.ObjectDisposedException: The object was used after being disposed.
  at System.Net.Sockets.UdpClient.CheckDisposed () [0x00000] in <filename unknown>:0 
  at System.Net.Sockets.UdpClient.Receive (System.Net.IPEndPoint remoteEP) [0x00000] in <filename unknown>:0 
  at UDPReceiver.ReceiveUDPData () [0x0001d] in xxxxxxxxxxxxxxxxxxx\UDPReceiver.cs:95

If I terminate LabView program before stopping the game at Unity, everything works as planned.

I have added the following lines at the end of the code. I have tried both OnDisable and this OnApplicationQuit.

    void OnApplicationQuit () {

        if (receiveThread != null) 
            receiveThread.Abort();
        
        receiver.Close();
    }

How can I handle this situation when the server is still sending messages when I’m trying to close the connection in Unity? Usually I cannot stop the UDP sending in LabView since the messages are also used in other purposes at the same time.

Jukkauuno: Small tip, use the Lidgren Networking Library instead, rock solid UDP implementation that works on Mono and .NET

Does it work in Web Player?

Does anyone have this example codes working in a project to see how it is implemented? Thanks.