Skip to content

Instantly share code, notes, and snippets.

@danielbierwirth
Last active April 5, 2024 21:57
Show Gist options
  • Save danielbierwirth/0636650b005834204cb19ef5ae6ccedb to your computer and use it in GitHub Desktop.
Save danielbierwirth/0636650b005834204cb19ef5ae6ccedb to your computer and use it in GitHub Desktop.
TCP Client-Server Connection Example | Unity | C# | Bidirectional communication sample: Client can connect to server; Client can send and receive messages: Server accepts clients; Server reads client messages; Server sends messages to client
// This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
// To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/
// or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;
public class TCPTestClient : MonoBehaviour {
#region private members
private TcpClient socketConnection;
private Thread clientReceiveThread;
#endregion
// Use this for initialization
void Start () {
ConnectToTcpServer();
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(KeyCode.Space)) {
SendMessage();
}
}
/// <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() {
try {
socketConnection = new TcpClient("localhost", 8052);
Byte[] bytes = new Byte[1024];
while (true) {
// 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) {
var incommingData = new byte[length];
Array.Copy(bytes, 0, incommingData, 0, length);
// Convert byte array to string message.
string serverMessage = Encoding.ASCII.GetString(incommingData);
Debug.Log("server message received as: " + serverMessage);
}
}
}
}
catch (SocketException socketException) {
Debug.Log("Socket exception: " + socketException);
}
}
/// <summary>
/// Send message to server using socket connection.
/// </summary>
private void SendMessage() {
if (socketConnection == null) {
return;
}
try {
// Get a stream object for writing.
NetworkStream stream = socketConnection.GetStream();
if (stream.CanWrite) {
string clientMessage = "This is a message from one of your clients.";
// Convert string message to byte array.
byte[] clientMessageAsByteArray = Encoding.ASCII.GetBytes(clientMessage);
// Write byte array to socketConnection stream.
stream.Write(clientMessageAsByteArray, 0, clientMessageAsByteArray.Length);
Debug.Log("Client sent his message - should be received by server");
}
}
catch (SocketException socketException) {
Debug.Log("Socket exception: " + socketException);
}
}
}
// This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
// To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/
// or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;
public class TCPTestServer : MonoBehaviour {
#region private members
/// <summary>
/// TCPListener to listen for incomming TCP connection
/// requests.
/// </summary>
private TcpListener tcpListener;
/// <summary>
/// Background thread for TcpServer workload.
/// </summary>
private Thread tcpListenerThread;
/// <summary>
/// Create handle to connected tcp client.
/// </summary>
private TcpClient connectedTcpClient;
#endregion
// Use this for initialization
void Start () {
// Start TcpServer background thread
tcpListenerThread = new Thread (new ThreadStart(ListenForIncommingRequests));
tcpListenerThread.IsBackground = true;
tcpListenerThread.Start();
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(KeyCode.Space)) {
SendMessage();
}
}
/// <summary>
/// Runs in background TcpServerThread; Handles incomming TcpClient requests
/// </summary>
private void ListenForIncommingRequests () {
try {
// Create listener on localhost port 8052.
tcpListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 8052);
tcpListener.Start();
Debug.Log("Server is listening");
Byte[] bytes = new Byte[1024];
while (true) {
using (connectedTcpClient = tcpListener.AcceptTcpClient()) {
// Get a stream object for reading
using (NetworkStream stream = connectedTcpClient.GetStream()) {
int length;
// Read incomming stream into byte arrary.
while ((length = stream.Read(bytes, 0, bytes.Length)) != 0) {
var incommingData = new byte[length];
Array.Copy(bytes, 0, incommingData, 0, length);
// Convert byte array to string message.
string clientMessage = Encoding.ASCII.GetString(incommingData);
Debug.Log("client message received as: " + clientMessage);
}
}
}
}
}
catch (SocketException socketException) {
Debug.Log("SocketException " + socketException.ToString());
}
}
/// <summary>
/// Send message to client using socket connection.
/// </summary>
private void SendMessage() {
if (connectedTcpClient == null) {
return;
}
try {
// Get a stream object for writing.
NetworkStream stream = connectedTcpClient.GetStream();
if (stream.CanWrite) {
string serverMessage = "This is a message from your server.";
// Convert string message to byte array.
byte[] serverMessageAsByteArray = Encoding.ASCII.GetBytes(serverMessage);
// Write byte array to socketConnection stream.
stream.Write(serverMessageAsByteArray, 0, serverMessageAsByteArray.Length);
Debug.Log("Server sent his message - should be received by client");
}
}
catch (SocketException socketException) {
Debug.Log("Socket exception: " + socketException);
}
}
}
@gwc593
Copy link

gwc593 commented Aug 6, 2018

Tried to apply TCPTestClient.cs to an object within my unity scene, fails with:

"Can't add script behaviour VisualContainerAsset. The script needs to derive from MonoBehaviour!"

I dont understand this, as the class you have written is derived from MonoBehaviour, any ideas?

@dinhtona
Copy link

How can i use them (client and server both) in one application, after builed, who are first run is a server, and second run is client.
Any solu, many thank !

@pvancamp
Copy link

gwc59s commented: "Can't add script behaviour VisualContainerAsset. The script needs to derive from MonoBehaviour!"

Make sure name of the class matches the name of your file.

@Sarthakg91
Copy link

Thanks for sharing! Wondering how do you close the thread when the client wants to quit?

@jaakaappi
Copy link

btw SendMessage is a function in the Unity Component class

@henrylovedesign
Copy link

Hi,thanks for your code! I write a server in python ,and use your c# code as client,when I sent the data for the first time i press the space key,it is ok, but the second time fail

@furkanbrbr
Copy link

This server is Synchronous or Asynchronous ? Which one ?

@Karim-Sheetos2269
Copy link

how get a multiple client ??

@shubhamguptak
Copy link

I am trying to stream the data from Qstreamer directly to Unity through TCP/IP.
QStreamer is QUASAR’s data acquisition software with an intuitive user interface to control the system and acquire EEG data and stream it through TCP/IP.
Can you please tell me how should i approach

@diogomartino
Copy link

Thank you! Really usefull!

@sndsh7
Copy link

sndsh7 commented Jun 30, 2019

I have test scripts on same device it works grate !!! but when i tested same code with mobile and laptop it won't work i think i something missing in client side ip address what should i do, please help me,.. I use server pc IP address in client side script and both devices connected to same network

@nre0104
Copy link

nre0104 commented Jun 30, 2019

I have test scripts on same device it works grate !!! but when i tested same code with mobile and laptop it won't work i think i something missing in client side ip address what should i do, please help me,.. I use server pc IP address in client side script and both devices connected to same network

Have you tested it with a 3rd-party-client and server?
Did you have also checked your laptop's firewall?

@sndsh7
Copy link

sndsh7 commented Jul 3, 2019

I have test scripts on same device it works grate !!! but when i tested same code with mobile and laptop it won't work i think i something missing in client side ip address what should i do, please help me,.. I use server pc IP address in client side script and both devices connected to same network

Have you tested it with a 3rd-party-client and server?
Did you have also checked your laptop's firewall?

Yes, I have checked my firewall settings their is also everything is allow public and private for unity editor as well unity hub.

@idemax
Copy link

idemax commented Jul 5, 2019

Thanks a lot man! Great job!!!

@bayan47
Copy link

bayan47 commented Jul 6, 2019

Hi,all.
How can i kill thread for listenting, when player wants to quit?

@idemax
Copy link

idemax commented Jul 11, 2019

Hi,all.
How can i kill thread for listenting, when player wants to quit?

https://stackoverflow.com/a/1980528/575643

@sergiobd
Copy link

Hi,all.
How can i kill thread for listenting, when player wants to quit?

https://stackoverflow.com/a/1980528/575643

I think that will close the connection, but would not kill the thread.

@TheVeldt
Copy link

Thats awesome! thanks!

@LUISCR
Copy link

LUISCR commented Oct 21, 2019

I probe this with my arduino+esp8266. This working!!!!, Thanks a lot.

@Khiev
Copy link

Khiev commented Nov 14, 2019

កាក

@LittleMatjes
Copy link

Hi,
above was the question how to kill the thread.
The comment that only the connection is closed is right.
The thread still is alive.
In a unity build it is not the problem because when closing the exe the thread is destroyed.
But allways restarting Unity Editor is very ugly.
So who to kick the thread? Abort() does not work in this case ... Thread is still alive ...
Anybody any idea?

Thanks,
regards, Matthias

@ArturoElpidioLuiz
Copy link

Hi,
client script really helped me, but i don't know what about one thing. I use this to connect and communicate with server on RaspberryPi. It works great, but after i stop Unity and then close socket on Raspberry I get this in my console:

InvalidOperationException: The operation is not allowed on non-connected sockets.
System.Net.Sockets.TcpClient.GetStream () (at <14e3453b740b4bd690e8d4e5a013a715>:0)
tcpv3.ListenForData () (at Assets/Scenes/tcpv3.cs:56)
System.Threading.ThreadHelper.ThreadStart_Context (System.Object state) (at :0)
System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) (at :0)
System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) (at :0)
System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state) (at :0)
System.Threading.ThreadHelper.ThreadStart () (at :0)
UnityEngine.<>c:b__0_0(Object, UnhandledExceptionEventArgs)

What does it mean? Is this something with closing thread? I am pretty new to Unity and I don't know what should I do.

@ugurrrn
Copy link

ugurrrn commented May 3, 2021

Before close socket,you try close connections.
client.Close();

@luisferblink
Copy link

Excelent man
thank you for this codes, they help me a lot...

The Best !!!

@strykerb
Copy link

@danielbierwirth Any way you could add an open-source license to this code so that I may integrate it (with attribution) into an open source project I'm contributing to? It's a win-win; I do less work and your page gains visibility. If so, I would recommend CC BY-SA 4.0, which allows for modification and redistribution, with proper attribution.

To do so, simply add the following text as a comment or separate file:
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.

Thanks for your time and awesome code!

@zorderjohn
Copy link

I couldn't make the server work on Unity 2020.3. I tested several clients and but I couldn't connect (timeout). Then I changed IPAddress.Parse("127.0.0.1") to IPAddress.Any when creating the TcpListener and now everything works flawless.

@Rabie-zem
Copy link

How to use in the case where I'm sending object
I know that I should serialize it but while deserializing it I have a problem in the fonction of deserialization
Show this error :
FromJsonOverwite can only be called from the main thread.
What should I do!?

@philippwulff
Copy link

philippwulff commented Aug 18, 2022

Thanks for the code. I used the C# example for the client in Unity and wrote a server in Python. However I have problems with the rate at which I can send messages from the server to the client. I get BrokenPipeErrors when the rate is too fast. Maybe something about the ListenForData function in the client can be improved

@dnorambu
Copy link

The tcp port connection is not being freed since the client and server are running a background thread that only gets finished after closing or reloading the Editor (not totally sure about the last one), not after exiting play mode. So in order to reset the connection properly, call Close() on the server and the client, and make sure the threads can finish, adding a different condition inside the while(true) loops

@emindeniz99
Copy link

Is while true loop necessary? I found that disposable getstream usage closes that socket, so next iteration of while loop throws exception dur to closed socket.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment