Unity Version: 2018.3.0f2
A first point of note: Large swaths of this code is used from information found on this Matlab forum thread. I used this setup as part of a master’s capstone project. (I’m the only one on the team that’s really comfortable with Unity/C#).
A second point of note: I have so far failed to be able to talk between a server and client within a single Unity application, probably because I’m port blocking myself. So I’ve added both python and Matlab client and server scripts for testing.
It’s basically just C#, but slapped together into the Unity MonoBehaviour scripting framework to run them in a scene.
TCP Server
The TCP server/listener is in the TCPListenPipe.cs script. You feed it your address and port, and it sits there listening for clients that want to talk to it.
TCPListenPipe.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using UnityEngine;
namespace UnityTutorial
{
public class TCPListenPipe : MonoBehaviour
{
public String Host = "localhost";
public Int32 Port = 55000;
private TcpListener listener = null;
private TcpClient client = null;
private NetworkStream ns = null;
string msg;
// Start is called before the first frame update
void Awake()
{
listener = new TcpListener(Dns.GetHostEntry(Host).AddressList[1], Port);
listener.Start();
Debug.Log("is listening");
if (listener.Pending())
{
client = listener.AcceptTcpClient();
Debug.Log("Connected");
}
}
// Update is called once per frame
void Update()
{
if (client == null)
{
if (listener.Pending())
{
client = listener.AcceptTcpClient();
Debug.Log("Connected");
}
else
{
return;
}
}
ns = client.GetStream();
if ((ns != null) && (ns.DataAvailable))
{
StreamReader reader = new StreamReader(ns);
msg = reader.ReadToEnd();
Debug.Log(msg);
}
}
private void OnApplicationQuit()
{
if (listener != null)
listener.Stop();
}
}
}
A lot of this script is simply error handling so it doesn’t hang or miss seeing the client. To start, when it starts up it kicks off the listener and starts listening. If a client is already trying to make a connection then it accepts the client and it’s connected. If no one is trying to connect, it doesn’t hang up your Unity program over it, however.
Instead, in the update loop it checks if you have a client. If you don’t it checks if there’s a client asking to connect, if there is, it connects and continues on. If there’s not, then it exits the update loop and skips all attempts to read from a client (as there is no client connected!).
Once it connects to a client, then every update frame is gets new data, reads the stream, and then spits the data out in a way we can check it. (In this instance, via the Debug Log.)
TCP Client
TCPSendPipe.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using UnityEngine;
namespace UnityTutorial
{
public class TCPSendPipe : MonoBehaviour
{
public String Host = "localhost";
public Int32 Port = 55000;
TcpClient mySocket = null;
NetworkStream theStream = null;
StreamWriter theWriter = null;
// Start is called before the first frame update
void Start()
{
mySocket = new TcpClient();
if (SetupSocket())
{
Debug.Log("socket is set up");
}
}
// Update is called once per frame
void Update()
{
if (!mySocket.Connected)
{
SetupSocket();
}
}
public bool SetupSocket()
{
try
{
mySocket.Connect(Host, Port);
theStream = mySocket.GetStream();
theWriter = new StreamWriter(theStream);
Byte[] sendBytes = System.Text.Encoding.UTF8.GetBytes("yah!! it works");
mySocket.GetStream().Write(sendBytes, 0, sendBytes.Length);
Debug.Log("socket is sent");
return true;
}
catch (Exception e)
{
Debug.Log("Socket error: " + e);
return false;
}
}
private void OnApplicationQuit()
{
if (mySocket != null && mySocket.Connected)
mySocket.Close();
}
}
}
A lot of this is also intended for error handling and good practices, so we’ll quickly jump through the different pieces.
Starting with the class variables:
Host and port are self explanatory, make sure they match so your servers and clients find each other. The socket, stream, and stream writer are the workhorses, where the socket is your actual connection, the network stream is the data feed between the client and server, and the writer takes your data, and injects it into the stream between the two.
Start and Update are just handling trying to connect to the server no matter which order you run your server and client in. The OnApplicationQuit is simply intended as cleanup of any remaining open sockets.
SetupSocket it the part we care about, which attempts to connect to the host, then gets the stream, turns our message into bytes, and then writes our stream to the socket. If it fails it lets you know it failed in the Debug Log.
Python and Matlab
As I noted earlier, both Python and Matlab client/server scripts have been provided for testing. I’m not going to go over them, because the other side of the connection is a bit out of scope for this tutorial. However, they are listed in their respective folders in the tutorial repository.
pythonReceive.py
#!/usr/bin/env python
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 55000
BUFFER_SIZE = 20 # Normally 1024, but we want fast response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connection address:', addr
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
print "received data:", data
conn.close()
pythonSend.py
#!/usr/bin/env python
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 55000
MESSAGE = "Hello, World!"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE)
s.close()
matlabReceive.m
clc
clear all
tcpipServer = tcpip('0.0.0.0',55000,'NetworkRole','Server');
while(1)
data = membrane(1);
fopen(tcpipServer);
rawData = fread(tcpipServer,14,'char');
for i=1:14 rawwData(i)= char(rawData(i));
end
fclose(tcpipServer);
end
matlabSend.m
clc
clear all
tcpipClient = tcpip('127.0.0.1',55000,'NetworkRole','Client');
set(tcpipClient,'Timeout',30);
fopen(tcpipClient);
a='yah!! we could make it';
fwrite(tcpipClient,a);
fclose(tcpipClient);
The full Unity package for this tutorial is at our github here. So take a look or ping us if you have any difficulties.