I am working my way trough socket tutorials and I am running in to a problem. I have 3 classes; Server, ServerClient and Client. The Server listens for connections requests, the ServerClient is the server side Socket wrapper and the Client is a user side program trying to connect.
The problem I am facing, is that when the Server passes the accepted socket to the ServerClient class the Socket is disconnected. If I debug the Socket passed has Connected = True, but when I set the local variable in ServerClient it becomes Connected = False.
On the Client side I am not facing problems yet know to me, that Socket remains Connected.
What am I doing wrong, and what else sucks about my code?
Server:
public async void Run()
{
//
if (AcceptingClients)
{
// Error already running
return;
}
//
LoadSettings();
//
IPEndPoint localEndPoint = new IPEndPoint(_settings.Ip, _settings.Port);
// Start The Server
_server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_server.Bind(localEndPoint);
_server.Listen(100);
//
AcceptingClients = true;
//
OnServerStart(EventArgs.Empty);
// Running => Accept connections
await AcceptConnections();
// Stopped => Close connections
await CloseConnections();
// Server Stopped => Finish stuff
//
OnServerStop(EventArgs.Empty);
}
private async Task AcceptConnections()
{
await Task.Run(() =>
{
while (AcceptingClients)
{
try
{
// Set the _acceptConnectionDone to nonsignaled state.
_acceptConnectionDone.Reset();
//
_server.BeginAccept(AcceptConnectionsCallback, _server);
// Wait until a connection is made before continuing.
_acceptConnectionDone.WaitOne();
}
catch
{
//
}
}
});
}
private static void AcceptConnectionsCallback(IAsyncResult ar)
{
// Signal the AcceptConnections Task to continue.
_acceptConnectionDone.Set();
//
if (!AcceptingClients)
{
// Server Stopping or stopped
return;
}
// Get the socket that handles the client request.
Socket server = (Socket)ar.AsyncState;
Socket client = server.EndAccept(ar);
// Create the client object.
ServerClient newclient = new ServerClient(client);
// Add Events
//
_connections.TryAdd(_totalConnectionCount++, newclient);
}
ServerClient:
private readonly Socket _connection;
//
public ServerClient(Socket s)
{
//
_connection = s;
//
Run();
// Disconnected or needs to be disconnected => Process
Disconnect();
return;
}
private async void Run()
{
//
if (_connection.Connected)
{
//
_connection.ReceiveBufferSize = ServerExt.ReadBufferSize;
_connection.SendBufferSize = ServerExt.SendBufferSize;
_connection.NoDelay = true;
//
await ListenToClient();
}
}
Client:
public async void Connect()
{
if (_connection != null)
{
// Check if we are not connected already
}
//
LoadSettings();
//
try
{
//
IPEndPoint remoteEndPoint = new IPEndPoint(_settings.Ip, _settings.Port);
// Create a TCP/IP socket.
_connection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
{
ReceiveBufferSize = ServerExt.ReadBufferSize,
SendBufferSize = ServerExt.SendBufferSize,
NoDelay = true
};
// Connect to the remote endpoint.
_connection.Connect(remoteEndPoint);
//
if (_connection.Connected)
{
//
await ListenToServer();
}
}
catch
{
//
}
// Disconnected or needs to be disconnected => Process
Disconnect();
return;
}
Thnx.
I managed to keep the connection open by changing the code for ServerClient.
public ServerClient(int id, Socket s, ClientConnectedDelegate connected, ClientDisconnectedDelegate disconnected)
{
//
Id = id;
//
_connection = s;
_disconnected = disconnected;
//
Ip = _connection.RemoteIp();
//
_connection.ReceiveBufferSize = ServerExt.ReadBufferSize;
_connection.SendBufferSize = ServerExt.SendBufferSize;
_connection.NoDelay = true;
//
_netStream = new NetworkStream(_connection, FileAccess.ReadWrite);
//
if (_cert != null)
{
_ssl = new SslStream(_netStream, false);
_ssl.AuthenticateAsServer(_cert, false, SslProtocols.Tls, true);
//
_br = new BinaryReader(_ssl, Encoding.UTF8, false);
_bw = new BinaryWriter(_ssl, Encoding.UTF8, false);
}
else
{
_br = new BinaryReader(_netStream, Encoding.UTF8, false);
_bw = new BinaryWriter(_netStream, Encoding.UTF8, false);
}
//
Task.Factory.StartNew(ListenToClient);
//
connected(this);
}
Related
I have a console application which acts as a socket server. It should accept data 24/7 from a number of clients, but issue is that the clients cannot establish connection after sometime (not constant). after closing & opening the connection works & it continues to next point of time.
Server
public static void ExecuteServer()
{
int portNumber = 11111;
string _responseMessageToClient = "";
IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddr, portNumber);
// Creation TCP/IP Socket using
// Socket Class Costructor
Socket listener = new Socket(ipAddr.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
bool doBroadCast = false;
try
{
listener.Bind(localEndPoint);
listener.Listen(10);
while (true)
{
try`enter code here`
{
Socket clientSocket = listener.Accept();
// Data buffer
byte[] bytes = new Byte[1024*2];//2048
string data = null;
while (true)
{
try
{
if (clientSocket.Connected)
{
int numByte = clientSocket.Receive(bytes);
data += Encoding.ASCII.GetString(bytes,
0, numByte);
if (data.IndexOf("!") > -1)
break;
}
else
{
Console.WriteLine("Disconnected {0}", clientSocket.LocalEndPoint);
break;
}
}
catch (Exception e)
{
//ErrorLogProvider.Save(e);
Console.WriteLine(e.ToString());
break;
}
}
Console.WriteLine("Text received -> {0} ", data);
if (clientSocket.Connected)
{
clientSocket.Send(message);
}
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
}
catch (Exception e)
{
}
}
}
catch (Exception e)
{
}
}
This server has to be running continuously - Client code given below
static void ExecuteClient()
{
try
{
// Establish the remote endpoint
// for the socket. This example
// uses port 11111 on the local
// computer.
int portNumber = 11111;
IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddr, portNumber);
// Creation TCP/IP Socket using
// Socket Class Costructor
Socket sender = new Socket(ipAddr.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
long i = 0;
try
{
//while (i < 10)
//{
// Connect Socket to the remote
// endpoint using method Connect()
sender.Connect(localEndPoint);
// We print EndPoint information
// that we are connected
Console.WriteLine("Socket connected to -> {0} ",
sender.RemoteEndPoint.ToString());
// Creation of messagge that
// we will send to Server
byte[] messageSent = Encoding.ASCII.GetBytes("^check!");
int byteSent = sender.Send(messageSent);
// Data buffer
byte[] messageReceived = new byte[1024];
// We receive the messagge using
// the method Receive(). This
// method returns number of bytes
// received, that we'll use to
// convert them to string
int byteRecv = sender.Receive(messageReceived);
Console.WriteLine("Message from Server -> {0}",
Encoding.ASCII.GetString(messageReceived,
0, byteRecv));
//}
// Close Socket using
// the method Close()
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
// Manage of Socket's Exceptions
catch (ArgumentNullException ane)
{
Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
}
catch (SocketException se)
{
Console.WriteLine("SocketException : {0}", se.ToString());
}
catch (Exception e)
{
Console.WriteLine("Unexpected exception : {0}", e.ToString());
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
I've got this code somewhere from SO if I remember that correctly.
LoopClients just checks for new clients and handles them by spawning a new thread.
class Server {
private TcpListener _server;
private Boolean _isRunning = true;
private int m_Port = 12001;
private Thread m_ServerThread;
public Server (int p_Port) {
_server = new TcpListener(IPAddress.Any, m_Port);
_server.Start( );
m_ServerThread = new Thread(new ThreadStart(LoopClients));
m_ServerThread.Start( );
}
public void ShutdownServer() {
_isRunning = false;
}
public void LoopClients ( ) {
while ( _isRunning ) {
// wait for client connection
TcpClient newClient = _server.AcceptTcpClient( );
// client found.
// create a thread to handle communication
Thread t = new Thread(new ParameterizedThreadStart(HandleClient));
t.Start(newClient);
}
}
public void HandleClient (object obj) {
try {
// retrieve client from parameter passed to thread
TcpClient client = (TcpClient) obj;
// sets two streams
StreamWriter sWriter = new StreamWriter(client.GetStream( ), Encoding.ASCII);
StreamReader sReader = new StreamReader(client.GetStream( ), Encoding.ASCII);
// you could use the NetworkStream to read and write,
// but there is no forcing flush, even when requested
String sData = null;
while ( client.Connected ) {
sData = sReader.ReadToEnd( );
if ( sData != "" )
break;
}
try {
sWriter.WriteLine("test");
} catch(Exception ex) {
Console.WriteLine(ex.Message);
}
sWriter.Dispose( );
sReader.Dispose( );
sWriter = null;
sReader = null;
} catch ( IOException ioe ) {
}
}
}
Client is somewhat shorter. I've got to shorten the code a bit here.
Client:
private void sendDataViaTCP () {
TcpClient l_Client = new TcpClient();
l_Client.Connect(IP, Port);
Stream l_Stream = l_Client.GetStream( );
StreamWriter l_SW = new StreamWriter(l_Stream);
StreamReader l_SR = new StreamReader(l_SW.BaseStream);
try {
l_SW.WriteLine(Msg);
l_SW.Flush( );
String l_IncomingData;
while ( ( l_IncomingData = l_SR.ReadToEnd()) != "") {
AddLineToLog(l_IncomingData);
}
} finally {
l_SW.Close( );
}
}
I'm trying to establish a socket connection between my Mobile device and Desktop. Mobile Device(Android) will act as a server while the desktop is client machine.
Following is my code for server,
public class PhoneCamera : MonoBehaviour
{
private TcpListener listner;
private const int port = 8010;
private bool stop = false;
private List<TcpClient> clients = new List<TcpClient>();
public void Start ()
{
Application.runInBackground = true;
initAndWaitForWebCamTexture();
}
void initAndWaitForWebCamTexture()
{
listner = new TcpListener(IPAddress.Any, port);
listner.Start();
//Start sending coroutine
StartCoroutine(senderCOR());
}
WaitForEndOfFrame endOfFrame = new WaitForEndOfFrame();
IEnumerator senderCOR()
{
bool isConnected = false;
TcpClient client = null;
NetworkStream stream = null;
// Wait for client to connect in another Thread
Loom.RunAsync(() =>
{
while (!stop)
{
// Wait for client connection
client = listner.AcceptTcpClient();
// We are connected
clients.Add(client);
isConnected = true;
stream = client.GetStream();
}
});
//Wait until client has connected
while (!isConnected)
{
yield return null;
}
LOG("Connected!");
}
void LOG(string messsage)
{
Debug.Log(messsage);
}
private void Update ()
{
}
}
Following is the code for client
public class Receiver : MonoBehaviour
{
public bool enableLog = false;
const int port = 8010;
public string IP = "192.168.122.24";
TcpClient client;
private bool stop = false;
//This must be the-same with SEND_COUNT on the server
const int SEND_RECEIVE_COUNT = 15;
// Use this for initialization
void Start()
{
Application.runInBackground = true;
tex = new Texture2D(0, 0);
client = new TcpClient();
//Connect to server from another Thread
Loom.RunAsync(() =>
{
LOGWARNING("Connecting to server...");
// if on desktop
client.Connect(IPAddress.Loopback, port);
// if using the IPAD
//client.Connect(IPAddress.Parse(IP), port);
Debug.Log("Connected");
});
}
void Update()
{
}
void OnApplicationQuit()
{
LOGWARNING("OnApplicationQuit");
stop = true;
if (client != null)
{
client.Close();
}
}
}
But for some reason, the client is not being to connect to the server running on Android. How can I be able to sort this out?
On TcpClient.Connect(IPEndPoint), you should specify the ip of the device you want to connect to.
client.Connect(IPAddress.Loopback, port);
Should be commented out, while
//client.Connect(IPAddress.Parse(IP), port);
Is IMHO the right code line.
I currently cannot test your code, and my reputation is too low to post this as a comment...sorry.
I want to use a C# plugin in my Unity project. That plugin should act as a server which will get values from a client so that I'd be able to use those values for further processing.
The issue is that the server has infinite loop. And infinite loops cause Unity to hang. How to handle this?
EDIT: I'm attaching a code snippet of server program. In my opinion, there are 2 points which may be causing problem. The infinite loops and the point where program is suspended as commented in code:
void networkCode()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// Dns.GetHostName returns the name of the
// host running the application.
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 1755);
// Create a TCP/IP socket.
listener = new Socket(ipAddress.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)
{
// Program is suspended while waiting for an incoming connection.
Debug.Log("HELLO"); //It works
handler = listener.Accept();
Debug.Log("HELLO"); //It doesn't work
data = null;
// An incoming connection needs to be processed.
while (true)
{
bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
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());
}
}
EDIT: After help from #Programmer, the C# plugin is complete. But Unity is not reading the correct values. I'm attaching the Unity side code:
using UnityEngine;
using System;
using SyncServerDLL; //That's our library
public class receiver : MonoBehaviour {
SynchronousSocketListener obj; //That's object to call server methods
// Use this for initialization
void Start() {
obj = new SynchronousSocketListener ();
obj.startServer ();
}
// Update is called once per frame
void Update() {
Debug.Log (obj.data);
}
}
I have tested SynchronousSocketListener class thoroughly in Visual Studio. It is giving good results there.
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();
}
I want to use a C# plugin in my Unity project. That plugin should act as a server which will get values from a client so that I'd be able to use those values for further processing.
The issue is that the server has infinite loop. And infinite loops cause Unity to hang. How to handle this?
EDIT: I'm attaching a code snippet of server program. In my opinion, there are 2 points which may be causing problem. The infinite loops and the point where program is suspended as commented in code:
void networkCode()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// Dns.GetHostName returns the name of the
// host running the application.
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 1755);
// Create a TCP/IP socket.
listener = new Socket(ipAddress.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)
{
// Program is suspended while waiting for an incoming connection.
Debug.Log("HELLO"); //It works
handler = listener.Accept();
Debug.Log("HELLO"); //It doesn't work
data = null;
// An incoming connection needs to be processed.
while (true)
{
bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
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());
}
}
EDIT: After help from #Programmer, the C# plugin is complete. But Unity is not reading the correct values. I'm attaching the Unity side code:
using UnityEngine;
using System;
using SyncServerDLL; //That's our library
public class receiver : MonoBehaviour {
SynchronousSocketListener obj; //That's object to call server methods
// Use this for initialization
void Start() {
obj = new SynchronousSocketListener ();
obj.startServer ();
}
// Update is called once per frame
void Update() {
Debug.Log (obj.data);
}
}
I have tested SynchronousSocketListener class thoroughly in Visual Studio. It is giving good results there.
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();
}
I want to use a C# plugin in my Unity project. That plugin should act as a server which will get values from a client so that I'd be able to use those values for further processing.
The issue is that the server has infinite loop. And infinite loops cause Unity to hang. How to handle this?
EDIT: I'm attaching a code snippet of server program. In my opinion, there are 2 points which may be causing problem. The infinite loops and the point where program is suspended as commented in code:
void networkCode()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// Dns.GetHostName returns the name of the
// host running the application.
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 1755);
// Create a TCP/IP socket.
listener = new Socket(ipAddress.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)
{
// Program is suspended while waiting for an incoming connection.
Debug.Log("HELLO"); //It works
handler = listener.Accept();
Debug.Log("HELLO"); //It doesn't work
data = null;
// An incoming connection needs to be processed.
while (true)
{
bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
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());
}
}
EDIT: After help from #Programmer, the C# plugin is complete. But Unity is not reading the correct values. I'm attaching the Unity side code:
using UnityEngine;
using System;
using SyncServerDLL; //That's our library
public class receiver : MonoBehaviour {
SynchronousSocketListener obj; //That's object to call server methods
// Use this for initialization
void Start() {
obj = new SynchronousSocketListener ();
obj.startServer ();
}
// Update is called once per frame
void Update() {
Debug.Log (obj.data);
}
}
I have tested SynchronousSocketListener class thoroughly in Visual Studio. It is giving good results there.
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();
}