Hi guys, I think my last question was misinterpreted, so here is a more simple one.
How to create a TCP server and Client in unity? I don’t want to use unity network layer, this game will connect to a C++ server so I need it to talk to this server someway.
I’m completely lost, all my tries resulted in failure.
Edit:
This the code that is problematic, whenever i call "Socket soc = listener.AcceptSocket();"Unity crashes, I’ve tried putting it inside a coroutine without sucess.
using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Net.Sockets;
public class ServerClass : MonoBehaviour
{
TcpListener listener;
public void Start()
{
listener = new TcpListener(2033);
listener.Start();
}
public void Update()
{
if(!listener.Pending())
{
Debug.Log("Nothing to do here");
}
else
{
Socket soc = listener.AcceptSocket();
[...]
}
}
}
AcceptSocket is a blocking call - you don’t want to be calling that unless you know that there is a request pending - you can tell that using this. Otherwise Unity will hang until a request appears.
Coroutines are not threads - a coroutine that blocks will lock up Unity.
Ok so you can use my Loom class to interact with other thread (per the comments to my answer above - this is too long to be a comment) which lets you do this:
void Update() {
if(somethingHappened)
{
Loom.RunAsync(()=>{
//Your other thread code goes here
//e.g. SendStuff();
//If you need to then call back to the game
Loom.QueueOnMainThread(()=>{
//Code triggered from the other thread that
//accesses Unity object goes here
});
});
}
}
#Loom.cs#
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Threading;
using System.Linq;
//Loom handles threading
public class Loom : MonoBehaviour
{
private static Loom _current;
public static Loom Current
{
get
{
if (_current == null && Application.isPlaying)
{
var g = GameObject.Find("Loom");
if(g==null)
{
g = new GameObject("Loom");
g.hideFlags = HideFlags.HideAndDontSave;
}
_current = g.GetComponent<Loom>() ?? g.AddComponent<Loom>();
}
return _current;
}
}
void Awake()
{
if(_current != null && _current != this)
{
DestroyImmediate(gameObject);
}
else
{
_current = this;
}
}
private List<Action> _actions = new List<Action>();
public class DelayedQueueItem
{
public float time;
public Action action;
public string name;
}
private List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>();
public static void QueueOnMainThread(Action action, float time, string name)
{
lock(Current._delayed)
{
if(Current._delayed.Any(d=>d.name==name))
return;
QueueOnMainThread(action, time);
}
}
public static void QueueOnMainThread(Action action, string name)
{
QueueOnMainThread(action, 0, name);
}
public static void QueueOnMainThread(Action action, float time)
{
if (time != 0)
{
lock (Current._delayed)
{
Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action});
}
}
else
{
lock (Current._actions)
{
Current._actions.Add(action);
}
}
}
public static void QueueOnMainThread(Action action)
{
lock (Current._actions)
{
Current._actions.Add(action);
}
}
public static void RunAsync(Action a)
{
var t = new Thread(RunAction);
t.Priority = System.Threading.ThreadPriority.Normal;
t.Start(a);
}
private static void RunAction(object action)
{
((Action)action)();
}
Action[] toBeRun = new Action[1000];
DelayedQueueItem[] toBeDelayed = new DelayedQueueItem[1000];
void Update()
{
try
{
var actions = 0;
var delayedCount = 0;
//Process the non-delayed actions
lock (_actions)
{
for(var i = 0; i < _actions.Count; i++)
{
toBeRun[actions++] = _actions*;*
Check this brilliant presentation. There is a chapter with full example based on .net sockets, server and client side. Very clean and easy code. You will realize why async socket operations like BeginConnect, BeginReceive and so are needed to make it running with Unity.
If you are going to connect to a C++ Server, why do you want to create a TCP server in Unity? And since you don’t want to use the Unity network layer, this is not a Unity question any more.