Simple Socket Server in Unity

Simple socket server in Unity

Use Thread to do your server Listen and read and write actions.
You can declare socket and other networkstream objects as public then initialize them in a thread function.

Unity does not work well with while loops in Threads and may freeze sometimes, but you can fix that by adding System.Threading.Thread.Sleep(1); in your while loop where you are reading or waiting for data to arrive from socket.

Make sure to stop the Thread in OnDisable() function. Do NOT access Unity API from the new Thread function. Just do only the socket stuff there and return the data to a public variable.

System.Threading.Thread SocketThread;
volatile bool keepReading = false;

// Use this for initialization
void Start()
{
Application.runInBackground = true;
startServer();
}

void startServer()
{
SocketThread = new System.Threading.Thread(networkCode);
SocketThread.IsBackground = true;
SocketThread.Start();
}

private string getIPAddress()
{
IPHostEntry host;
string localIP = "";
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
localIP = ip.ToString();
}

}
return localIP;
}

Socket listener;
Socket handler;

void networkCode()
{
string data;

// Data buffer for incoming data.
byte[] bytes = new Byte[1024];

// host running the application.
Debug.Log("Ip " + getIPAddress().ToString());
IPAddress[] ipArray = Dns.GetHostAddresses(getIPAddress());
IPEndPoint localEndPoint = new IPEndPoint(ipArray[0], 1755);

// Create a TCP/IP socket.
listener = new Socket(ipArray[0].AddressFamily,
SocketType.Stream, ProtocolType.Tcp);

// Bind the socket to the local endpoint and
// listen for incoming connections.

try
{
listener.Bind(localEndPoint);
listener.Listen(10);

// Start listening for connections.
while (true)
{
keepReading = true;

// Program is suspended while waiting for an incoming connection.
Debug.Log("Waiting for Connection"); //It works

handler = listener.Accept();
Debug.Log("Client Connected"); //It doesn't work
data = null;

// An incoming connection needs to be processed.
while (keepReading)
{
bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
Debug.Log("Received from Server");

if (bytesRec <= 0)
{
keepReading = false;
handler.Disconnect(true);
break;
}

data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
if (data.IndexOf("<EOF>") > -1)
{
break;
}

System.Threading.Thread.Sleep(1);
}

System.Threading.Thread.Sleep(1);
}
}
catch (Exception e)
{
Debug.Log(e.ToString());
}
}

void stopServer()
{
keepReading = false;

//stop thread
if (SocketThread != null)
{
SocketThread.Abort();
}

if (handler != null && handler.Connected)
{
handler.Disconnect(false);
Debug.Log("Disconnected!");
}
}

void OnDisable()
{
stopServer();
}

How to improve data synchronization using Unity an multicast UDP socket

Network I/O is subject to a large number of external influences, and TCP/IP as a protocol has few requirements. Certainly none that would provide a guarantee of the behavior you seem to want.

Unfortunately, without a good Minimal, Complete, and Verifiable code example, it's not possible to verify that your server is in fact sending data at the interval you claim. It's entirely possible you have a bug that's causing this behavior.

But if we assume that the code itself is perfect, there are still no guarantees when using UDP that datagrams won't be batched up at some point along the way, such that a large number appear in the network buffer all at once. I would expect this to happen with higher frequency when the datagrams are sent through multiple network nodes (e.g. a switch and especially over the Internet), but it could just as easily happen when the server and client are both on the same computer.

Ironically, one option that might force the datagrams to be spread out more is to pad each datagram with extra bytes. The exact number of bytes required would depend on the exact network route; to do this "perfectly" might require writing some calibration logic that tries different padding amounts until the code sees datagrams arriving at the intervals it expects.

But that would significantly increase the complexity of your network I/O code, and yet still would not guarantee the behavior you'd like. And it has some obvious negative side-effects, including the extra overhead on the network (something people using metered network connections certainly won't appreciate), as well as increasing the likelihood of a UDP datagram being dropped altogether.

It's not clear from your question whether your project actually requires multicast UDP, or if that's just something in your code because that's what some tutorial or other example you're following was using. If multicast is not actually a requirement, another thing you definitely should try is to use direct UDP without multicasting.

FWIW: I would not implement this the way you have. Instead, I would use asynchronous receive operations, so that my client receives datagrams the instant they are available, rather than only checking periodically each frame of rendering. I would also include a sequence number in the datagram, and discard (ignore) any datagrams that arrive out of sequence (i.e. where the sequence number isn't strictly greater than the most recent sequence number already received). This approach will improve (perhaps only slightly) responsiveness, but also will handle situations where the datagrams arrive out of order, or are duplicated (two of the three main delivery issues one will experience with UDP…the third being, of course, failure of delivery).

Server logic for Unity simple game

For something really simple, I'd recommend using your own implementation of socket.io in your client application (c#) and a really basic nodeJS server using socket.io.

You have built in rooms, event sending/handling it's pretty handy.

For unity there is a paid asset (BestHTTP that is really good) and a free one (socket.io for unity or something like that).

You can then use your node server to connect to your database and send data to unity.

Hope it helped !

How to setup Socket.io server for Unity on Digital Ocean?

You mentioned you created a Digital Ocean account, and I am assuming you are running a varient of Linux (Debian/Ubuntu). For the server, you are going to need to install Node.js and NPM so that you can fetch the socket.io library. For the distro-stable version:

  1. sudo apt-get update
  2. sudo apt-get install nodejs
  3. sudo apt-get install npm

From here, a tutorial/simple server can be found here. This tutorial is for building a socket.io server for a chat app, but you can tailor it to the needs for your game.

For your Unity game itself, I think what you are looking for is socket.io-unity. This will allow your game to act as a socket.io client to communicate with your socket.io server running in Node.js.

Unity socket program doesn't run

First of all, Unity does not have a Main function like a normal C# program. So putting a code in public static void Main() will not do anything. Unity uses Start() and other simliar functions as it's starting point not Main().

Socket.cs is placed on assets directory in unity game

Simply placing a script in the Asset Folder does not mean it will work. You have to instantiate the script from another Unity script or attach the Script to a GameObject.

Also even if the code worked in Unity, Unity would freeze because the socket code is synchronous instead of asynchronous. It will block while reading or waiting for client to connect.

You should either make it with a Thread or use asynchronous socket.

Here is complete Unity TCP server that works in Unity. It uses Thread.

I suggest you learn how Unity works. Learn the basic.



Related Topics



Leave a reply



Submit