-
If I open a .NET socket in C# and don’t connect to it before hitting the STOP button in the editor the socket binding is not removed. This prevents the app from binding the next time I hit PLAY.
-
If I am accessing the C# server script to send some data from a JavaScript is it possible to recompile the JS without fubaring Mono? Right now if I modify the JS the C# class seems to recompile (or something is moved in memory?) causing null exceptions within the C# script. The script is a modified version of the NetworkCursor server script on the Wiki.
-
The Mono impl. used doesn’t seem to properly detect a socket that was closed from the remote machine. The isConnected() function (taken from the MSDN docs) as well as socket.Connected always return true after closing the connection.
Note I’ve done all the testing so far using Telnet to connect to the socket.
using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.Net;
using System.Text;
public class Server : MonoBehaviour {
public int port = 9349;
static Server theServer;
private Socket m_Socket;
ArrayList m_Connections = new ArrayList ();
ArrayList m_rBuffer = new ArrayList ();
ArrayList m_sBuffer = new ArrayList ();
ArrayList m_ByteBuffer = new ArrayList ();
void Awake ()
{
m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipLocal = new IPEndPoint ( IPAddress.Any , port);
m_Socket.Bind( ipLocal );
//start listening...
m_Socket.Listen (100);
theServer = this;
// Debug.Log("Listening on: " + ((IPEndPoint)m_Socket.LocalEndPoint).Address + ":" + ((IPEndPoint)m_Socket.LocalEndPoint).Port);
}
void OnApplicationQuit ()
{
Cleanup();
}
void Cleanup ()
{
if (m_Socket != null)
m_Socket.Close();
m_Socket = null;
foreach (Socket con in m_Connections)
con.Close();
m_Connections.Clear();
}
~Server ()
{
Cleanup();
}
void LateUpdate ()
{
// Accept any incoming connections!
ArrayList listenList = new ArrayList();
listenList.Add(m_Socket);
Socket.Select(listenList, null, null, 1000);
for( int i = 0; i < listenList.Count; i++ )
{
Socket newSocket = ((Socket)listenList[i]).Accept();
m_Connections.Add(newSocket);
m_ByteBuffer.Add(new ArrayList());
Debug.Log("Did connect");
}
if (m_Connections.Count != 0){
ArrayList connections = new ArrayList (m_Connections);
//Remove closed sockets from the list
foreach (Socket socket in connections){
if(isConnected(socket)==false){
socket.Close();
theServer.m_ByteBuffer.RemoveAt(m_Connections.IndexOf(socket));
theServer.m_Connections.Remove(socket);
}
}
}
// Read Write data from the connections!
if (m_Connections.Count != 0)
{
// Write data to connections
ArrayList connections = new ArrayList (m_Connections);
Socket.Select(null, connections, null, 1000);
while (theServer.m_sBuffer.Count>0){
byte[] sndBytes = new byte[((string)theServer.m_sBuffer[0]).Length];
string theString = (string)theServer.m_sBuffer[0];
for(int i=0;i<sndBytes.Length;i++){
sndBytes[i]=(byte)theString[i];
}
foreach(Socket socket in connections){
if(socket.Connected==false)break;
socket.Send(sndBytes);
}
theServer.m_sBuffer.RemoveAt(0);
}
connections = new ArrayList (m_Connections);
Socket.Select(connections, null, null, 1000);
// Go through all sockets that have data incoming!
foreach (Socket socket in connections)
{
if(socket.Connected==true){
byte[] receivedbytes = new byte[512];
ArrayList buffer = (ArrayList)m_ByteBuffer[m_Connections.IndexOf(socket)];
int read = socket.Receive(receivedbytes);
if(receivedbytes[0]!=0) {
for (int i=0;i<read;i++) buffer.Add(receivedbytes[i]);
}
while (buffer.Count > 0)
{
ArrayList thismsgBytes = new ArrayList(buffer);
int length=thismsgBytes.Count;
if (thismsgBytes.Count != length) Debug.Log("Bug");
buffer.RemoveRange(0, length);
byte[] readbytes = (byte[])thismsgBytes.ToArray(typeof(byte));
string readString = "";
foreach(byte b in readbytes){
readString+=(char)b;
}
// Debug.Log(readString);
theServer.m_rBuffer.Add(readString);
if (theServer != this)
Debug.Log("Bug");
}
}
}
}
}
//Get a message from the received queue
static public string GetMessage ()
{
if(theServer!=null){
if (theServer.m_rBuffer.Count == 0)
{
return null;
}
else
{
string readMsg = (string)theServer.m_rBuffer[0];
theServer.m_rBuffer.RemoveAt(0);
return readMsg;
}
}
else return null;
}
//Put a message in the outgoing queue
static public int PutMessage(string sendMsg){
if(theServer!=null){
if(theServer.m_sBuffer.Count>1000) theServer.m_sBuffer.Clear(); //if there is a backlog of more than 1000 messages clear the queue
return theServer.m_sBuffer.Add(sendMsg);
}
else return -1;
}
//Convert a string to a byte array
static ArrayList StringToBytes(string theString){
ArrayList bytes=new ArrayList();
foreach(char c in theString.ToCharArray()){
bytes.Add((byte)c);
}
return bytes;
}
//Returns true if there are messages waiting to be read in the received queue
static public int MessageAvailable(){
if(theServer!=null) return theServer.m_rBuffer.Count;
else return -1;
}
//Returns true if there are connections in the connection list
static public bool Connected(){
if(theServer!=null theServer.m_Connections.Count>0) return true;
else return false;
}
//Number of messages waiting to be sent
static public int SendBufferBackLog(){
if(theServer!=null)return theServer.m_sBuffer.Count;
else return -1;
}
//Clear the send buffer
static public void ClearSendBuffer(){
if(theServer!=null)theServer.m_sBuffer.Clear();
return;
}
//Check if a socket is still connected, questionable if this is working in Unity/Mono
static bool isConnected(Socket socket){
bool blockingState = socket.Blocking;
bool connected = false;
try
{
byte [] tmp = new byte[1];
socket.Blocking = false;
socket.Send(tmp, 0, 0);
connected = true;
}
catch (SocketException e)
{
// 10035 == WSAEWOULDBLOCK
if (e.NativeErrorCode.Equals(10035))
connected = true;
else
{
connected = false;
}
}
finally
{
socket.Blocking = blockingState;
}
return connected;
}
}
Jeff