public class MainServer
{
#region Constants
const int STATE_CLOSE = 0;
const int STATE_LOGIN = 1;
const int STATE_PLAYING = 2;
const int REQUESTS_PER_MIN = 60;
#endregion Constasnts
#region Fields
protected int m_nPort = 12345;
protected string m_strHost = "0.0.0.0";
protected bool m_bRunning = false;
protected Thread m_mainThread = null;
protected object m_objLock = new object();
protected Socket m_serverSocket = null;
protected Dictionary<Socket, ClientSocket> m_dicConnections = new Dictionary<Socket, ClientSocket>();
protected ConcurrentQueue<NetworkMessage> m_messageQueue = new ConcurrentQueue<NetworkMessage>();
protected AutoResetEvent m_evWaitForPendingMessages = new AutoResetEvent(false);
#endregion Fields
internal void Startup()
{
AutoResetEvent evWqaitForThreadToStart = new AutoResetEvent(false);
m_mainThread = new Thread(new ParameterizedThreadStart(MessageHandlerThread));
m_mainThread.Start(evWqaitForThreadToStart);
evWqaitForThreadToStart.WaitOne();
m_serverSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPAddress host = IPAddress.Parse(m_strHost);
IPEndPoint iep = new IPEndPoint(host, m_nPort);
m_serverSocket.Bind(iep);
m_serverSocket.Listen(2);
}
internal void Shutdown()
{
// stop running client thread
m_bRunning = false;
m_evWaitForPendingMessages.Set();
m_mainThread.Join();
// close server connections and disconnect existing clients
m_serverSocket.Close();
foreach (var key in m_dicConnections.Keys)
{
m_dicConnections[key].Disconnect();
}
m_dicConnections.Clear();
}
private void MessageHandlerThread(object obj)
{
m_bRunning = true;
AutoResetEvent evWqaitForThreadToStart = obj as AutoResetEvent;
evWqaitForThreadToStart .Set();
while (m_bRunning)
{
if (m_messageQueue.Count == 0)
{
m_evWaitForPendingMessages.WaitOne();
}
NetworkMessage netMsg = null;
m_messageQueue.TryDequeue(out netMsg);
if (netMsg == null)
{
continue;
}
switch (netMsg.Index)
{
// process network messages
default:
break;
}
}
// Shutting down
m_bRunning = false;
}
public void Run()
{
while (m_bRunning)
{
ListenForConnctions();
ManageInputData();
ManageOutputData();
// sleep 100 ms, suggest use a proper management of CPU overhead
Thread.Sleep(100);
}
}
private void ManageInputData()
{
// Make a copy
ArrayList copyList = new ArrayList();
foreach (var key in m_dicConnections.Keys)
{
copyList.Add(m_dicConnections[key].Socket);
}
if(copyList.Count == 0)
{
return;
}
Socket.Select(copyList, null, null, 0);
for (int nSocket = 0; nSocket < copyList.Count; nSocket++)
{
Socket socket = copyList[nSocket] as Socket;
ClientSocket client = m_dicConnections[socket];
if (client == null)
{
continue;
}
if (client.State == STATE_LOGIN)
{
client.LoginRequest++;
if (client.LoginRequest > REQUESTS_PER_MIN)
{
client.Disconnect();
m_dicConnections.Remove(socket);
continue;
}
}
if (client.Receive() <= 0)
{
client.Disconnect();
m_dicConnections.Remove(socket);
continue;
}
while (client.InputQueue.Count > 0)
{
NetworkMessage netMsg = client.InputQueue.Dequeue();
if (netMsg == null)
{
continue;
}
m_messageQueue.Enqueue(netMsg);
m_evWaitForPendingMessages.Set();
}
}
}
private void ManageOutputData()
{
List<Socket> socketsToDisconnect = new List<Socket>();
for (int nIndex = 0; nIndex < m_dicConnections.Count; nIndex++)
{
Socket socket = m_dicConnections.ElementAt(nIndex).Key;
ClientSocket client = m_dicConnections.ElementAt(nIndex).Value;
if (client.State == STATE_CLOSE || client.Send() <= 0)
{
client.Disconnect();
socketsToDisconnect.Add(socket);
continue;
}
}
for (int nIndex = 0; nIndex < socketsToDisconnect.Count; nIndex++)
{
Socket socket = socketsToDisconnect[nIndex];
m_dicConnections.Remove(socket);
}
}
private void ListenForConnctions()
{
try
{
ArrayList copyList = new ArrayList();
copyList.Add(m_serverSocket);
Socket.Select(copyList, null, null, 0);
if (copyList.Count == 0)
{
return;
}
Socket socket = m_serverSocket.Accept();
ClientSocket client = new ClientSocket(socket);
client.State = STATE_LOGIN;
m_dicConnections[socket] = (client);
}
catch (Exception ex)
{
// Socket error
}
}
}