For easier viewing download the code on the my code page or copy and paste into your IDE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
namespace Capstone_Networking_Project_Test_0
{
class Server
{
private Client[] clients = new Client[INetwork_Utils.MAX_CLIENTS];
private int numClients = -1;//0 index so client 0 is first client
private UdpClient listener;
private Track_Data track;
public Server()
{
track = new Track_Data();
listener = new UdpClient();
IPEndPoint localEP = new IPEndPoint(IPAddress.Any, INetwork_Utils.PORT_NUM);
listener.Client.Bind(localEP);
Listen();
}
private void Listen()
{
Console.WriteLine("Server online...");
bool newClient;
IPEndPoint recvFrom;
while (true)
{
newClient = true;
recvFrom = new IPEndPoint(IPAddress.Any, INetwork_Utils.PORT_NUM);
byte[] recieved = listener.Receive(ref recvFrom);
for (int i = 0; i < clients.Length; i++)
{
if (!(clients[i] is null) && IPEndPoint.Equals(recvFrom, clients[i].Ep) && clients[i].IsConnected)
{
newClient = false;
string converted = ASCIIEncoding.ASCII.GetString(recieved);
//UpdateTrack(i, converted, recvFrom);
UpdateTrack(i, converted);
break;
}
}
#region New Client
if (newClient)
{
Console.WriteLine("New Client");
if (numClients >= INetwork_Utils.MAX_CLIENTS)
{
string msg = INetwork_Utils.DISCONNECT + "";
byte[] data = ASCIIEncoding.ASCII.GetBytes(msg);
listener.Send(data, data.Length, recvFrom);
}
else
{
numClients++;
int i;
for ( i = 0; i < clients.Length; i++)
{
if (clients[i] is null || !clients[i].IsConnected)
break;
}
clients[i] = new Client(recvFrom, numClients);//write the new client over the old
FreshClient(recvFrom);
}
}
#endregion
}
}
private void UpdateTrack(int id, string msg)
{
int i, val, act;
string[] arr = msg.Split(INetwork_Utils.DELIM);
if (!int.TryParse(arr[0], out act))
Console.WriteLine("Message corrupted didnt find the action");
switch (act)
{
case INetwork_Utils.TURN://TURN;index;direction
#region Adjust turnout
if (arr.Length == 3 && int.TryParse(arr[1], out i) && int.TryParse(arr[2], out val))
{
Console.WriteLine("Sent from Client " + id + ": Turnout " + i + " was turned to face " + val);
track.AdjustTurnout(i, val);
SendToAllExcept(msg, id);
}
else
{
Console.WriteLine("Message corrupted couldnt change turnout");
//tell the client
}
break;
#endregion
case INetwork_Utils.SPEED://SPEED;index;speed
#region Adjust Speed
if (arr.Length == 3 && int.TryParse(arr[1], out i) && int.TryParse(arr[2], out val))
{
Console.WriteLine("Sent from Client " + id + ":Train " + i + " changed speed to " + val);
track.ChangeSpeed(clients[id].TrainIndex, val);
SendToAllExcept(msg, id);
}
else
{
Console.WriteLine("Message corrupted couldnt update speed");
//tell the client
}
#endregion
break;
case INetwork_Utils.ENTER://ENTER;index in;index out
#region Adjust sections
int direction;
if (arr.Length == 4 && int.TryParse(arr[1], out i) && int.TryParse(arr[2], out val) && int.TryParse(arr[3], out direction))
{
track.EnterSection(i, direction);
track.ExitSection(val);
Console.WriteLine("Sent from Client " + id + ": exiting section " + val + " entering section " + i);
SendToAllExcept(msg, id);
}
else
{
Console.WriteLine("Message corrupted couldnt update sections");
Console.WriteLine("Corrupted message = " + msg);
//tell the client
}
#endregion
break;
case INetwork_Utils.NEW_TRAIN://NEW_TRAIN;Train id;Train speed
#region Creating a new train
if (arr.Length == 4 && int.TryParse(arr[1], out i) && int.TryParse(arr[2], out val))
{
string username = arr[3];
Console.WriteLine("Sent from Client " + id + ": Added a new train with id " + i + " and speed " + val + " and username " + username);
int index = track.MakeTrain(i, val, username);
clients[id].TrainIndex = index;
SendToAllExcept(msg, id);
}
else
{
Console.WriteLine("Message corrupted couldnt update speed");
//tell the client
}
break;
#endregion
case INetwork_Utils.DISCONNECT://DISCONNECT;train id, section to open
#region Remove a Client
Console.WriteLine("Client " + id + " is trying to disconnect");
int trainID = int.Parse(arr[1]);
val = int.Parse(arr[2]);
RemoveClient(id);
int removedAt = track.RemoveTrain(trainID);
foreach (Client c in clients)
{
if (!(c is null) && c.TrainIndex > removedAt)
c.TrainIndex--;
}
track.ExitSection(val);
SendToAllExcept(msg, id);
break;
#endregion
}
}
private void RemoveClient(int id)
{
clients[id].IsConnected = false;
numClients--;
Console.WriteLine("Number of clients left =" + numClients);
if(numClients<0)
{
track.ResetTrack();
}
Console.WriteLine("Disconnected Client:" + id);
}
private void FreshClient(IPEndPoint ep)
{
string msg = track.GetTurns();
byte[] data = Encoding.ASCII.GetBytes(msg);
listener.Send(data, data.Length, ep);
Console.WriteLine("Sending turnouts as: " + msg);
msg = track.GetSections();
data = Encoding.ASCII.GetBytes(msg);
listener.Send(data, data.Length, ep);
Console.WriteLine("Sending sections as: " + msg);
msg = INetwork_Utils.LOC+"";
data = Encoding.ASCII.GetBytes(msg);//used to request locations of existing trains
string trainData = "";
listener.Client.ReceiveTimeout = INetwork_Utils.TIMEOUT;
for (int i = 0; i < INetwork_Utils.MAX_CLIENTS; i++)
{
if (!(clients[i] is null) && clients[i].IsConnected)
{
IPEndPoint addr = clients[i].Ep;
if (!(addr.Equals(ep)))//dont want to ask the client we are currently arranging
{
int count = 0;
retry://this section should be threaded...send messages to main thread and queue if they arent location messages
listener.Send(data, data.Length, addr);
try
{
byte[] recvd = listener.Receive(ref addr);
trainData += (Encoding.ASCII.GetString(recvd)) + INetwork_Utils.DELIM + track.GetNameAt(clients[i].TrainIndex) + INetwork_Utils.DELIM + track.SpeedAt(clients[i].TrainIndex) + INetwork_Utils.DELIM;
}
catch (SocketException)
{
Console.WriteLine("listen failed");
count++;
if(count<=5)
goto retry;//try 5 times then disconnect client
}
if (count == 6)
{
data = ASCIIEncoding.ASCII.GetBytes(INetwork_Utils.DISCONNECT+"");
listener.Send(data, data.Length, ep);
}
Console.WriteLine("Data after iteration " + i + trainData);
}
}
}
listener.Client.ReceiveTimeout = Timeout.Infinite;
if (trainData.Equals(""))
trainData = INetwork_Utils.NONE;
Console.WriteLine("Sending trains as: " + trainData);
data = Encoding.ASCII.GetBytes(trainData);
listener.Send(data, data.Length, ep);
}
private void SendToAllExcept(string msg, int index)
{
byte[] data = ASCIIEncoding.ASCII.GetBytes(msg);
for (int i = 0; i < INetwork_Utils.MAX_CLIENTS; i++)
{
if (!(clients[i] is null) && i != index && clients[i].IsConnected)
{
listener.Send(data, data.Length, clients[i].Ep);
listener.Send(data, data.Length, clients[i].Ep);
listener.Send(data, data.Length, clients[i].Ep);
Console.WriteLine("sent " + msg + " to client " + i);
}
}
}
}
}