This commit is contained in:
princessbobsanta 2016-04-27 00:53:00 -10:00
commit 91997b15b8
10 changed files with 756 additions and 0 deletions

View File

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server Application Console", "Server Application Console\Server Application Console.csproj", "{6F2E490C-75F7-4E37-A14C-434AD48656BB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6F2E490C-75F7-4E37-A14C-434AD48656BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6F2E490C-75F7-4E37-A14C-434AD48656BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6F2E490C-75F7-4E37-A14C-434AD48656BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6F2E490C-75F7-4E37-A14C-434AD48656BB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>

View File

@ -0,0 +1,178 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Server_Application_Console
{
class ChatServer : TCPServer
{
protected static TcpListener listener = null;
protected static bool listenerStarted = false;
private static uint currentID = 0;
private static uint expectedClient = 0;
public static readonly object IDLock = new object();
private Dictionary<TcpClient, string> clientList = new Dictionary<TcpClient, string>();
private bool running = true;
private uint serverID = 0;
//chat port
private readonly int port = 20113;
public static ManualResetEventSlim connectExpected = new ManualResetEventSlim(false);
public static ManualResetEventSlim connected = new ManualResetEventSlim(false);
public ChatServer(uint serverID)
{
this.serverID = serverID;
}
/*
public static void setConnectExpected(bool expected)
{
if(expected)
{
connectExpected.Set();
}
else
{
connectExpected.Reset();
}
}
public static bool getConnectExpected()
{
return connectExpected.IsSet;
}
*/
public static uint getCurrentID()
{
return currentID;
}
public static void setCurrentID(uint ID)
{
currentID = ID;
}
//starts a chat server
public async override Task startServer()
{
//attempts to start listener on chat port
if (!listenerStarted)
{
try
{
listener = new TcpListener(IPAddress.Any, port);
listener.Start();
listenerStarted = true;
}
//displays error box if unable to start server
catch (SocketException e)
{
Console.WriteLine("Unable to start the chat server, the socket is already in use.\n" + e.ToString());
}
}
//server control loop
while (running)
{
//checks if a new client is waiting to connect
if (listener.Pending() && currentID == serverID)
{
//connects to client
TcpClient client = await listener.AcceptTcpClientAsync();
//reads info from the client to ensure the proper client is attempting to connect
StreamReader reader = new StreamReader(client.GetStream());
StreamWriter writer = new StreamWriter(client.GetStream());
//if client attempting to connect directly without going through main server, denies connection (closes clients stream)
//may also occur if connection attempted aftr timeout
if (!(connectExpected.IsSet && reader.ReadLine().Equals(expectedClient.ToString()) && reader.ReadLine().Equals(currentID.ToString())))
{
writer.WriteLine("err");
writer.Flush();
client.GetStream().Close();
client.Close();
}
//else spawns new thread for handling data transmission to other clients
else
{
//reports to client if successfully connected
writer.WriteLine("success");
writer.Flush();
connectExpected.Reset();
Thread t = new Thread(transmitter);
t.Start(client);
connected.Set();
}
}
}
}
//sends messages to all clients
private void transmitter(Object client)
{
using (TcpClient thisClient = (TcpClient)client)
{
NetworkStream inStream = thisClient.GetStream();
string message = "";
StreamReader reader = new StreamReader(inStream);
//adds client to clientList, client name sent in clients stream
clientList.Add(thisClient, reader.ReadLine());
StreamWriter writer = null;
NetworkStream outStream;
while (thisClient.Connected && running)
{
//checks if data is available on the clients stream
if (inStream.DataAvailable)
{
message = reader.ReadLine();
//sends data to all clients in chat
foreach (KeyValuePair<TcpClient, string> c in clientList)
{
string clientName;
//creates StreamWriter for current outgoing client
outStream = c.Key.GetStream();
writer = new StreamWriter(outStream);
//appends sender name to beginning of message
clientList.TryGetValue(thisClient, out clientName);
//writes sender and message to outgoing stream
writer.WriteLine(clientName + ": " + message.ToString());
Console.WriteLine(clientName + ": " + message.ToString());
writer.Flush();
}
}
}
if (writer != null) { writer.Close(); }
if (reader != null) { reader.Close(); }
lock (clientList)
{
clientList.Remove(thisClient);
}
}
}
public override void stopServer()
{
if (listener != null) { listener.Stop(); }
running = false;
}
public static void setExpectedClient(uint clientID)
{
expectedClient = clientID;
}
}
}

View File

@ -0,0 +1,294 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Server_Application_Console
{
class MainServer : TCPServer
{
protected static TcpListener listener = null;
protected static bool listenerStarted = false;
//dictionary of connected clients by clientID
private Dictionary<uint, TcpClient> clientList = new Dictionary<uint, TcpClient>();
private bool running = true;
private static readonly object serverCounterLock = new Object();
private uint serverCounter = 0;
//main server port
private readonly int port = 20112;
public async override Task startServer()
{
//attempts to start listener on chat port
if (!listenerStarted)
{
try
{
//possible issues with conflicts if multiple chat servers running, to be fixed later
listener = new TcpListener(IPAddress.Any, port);
listener.Start();
}
//displays error box if unable to start server
catch (SocketException e)
{
Console.WriteLine("Unable to start the chat server, the socket is already in use.\n" + e.ToString());
}
}
//main server control
while (running)
{
//checks if a new client is waiting to connect
//if (listener.Pending())
// {
//connects to client
//currently connects to any client, possibly add security later
TcpClient client = await listener.AcceptTcpClientAsync();
//TcpClient client = listener.AcceptTcpClient();
NetworkStream stream = client.GetStream();
BinaryReader reader = new BinaryReader(stream);
byte type = reader.ReadByte();
//client type sends requests to server
if (type == 0)
{
Thread t = new Thread(transmitter);
t.Start(client);
}
//client type waits for requests from server
else if (type == 1)
{
uint thisClientID = reader.ReadUInt32();
//adds client to a dictionary for use
clientList.Add(thisClientID, client);
}
//}
}
}
//communicates between clients
private void transmitter(Object client)
{
using (TcpClient thisClient = (TcpClient)client)
{
NetworkStream stream = thisClient.GetStream();
BinaryReader reader = new BinaryReader(stream);
BinaryWriter writer = new BinaryWriter(stream);
uint thisClientID = reader.ReadUInt32();
//control while client connected and server running
while (thisClient.Connected && running)
{
//checks if data is available on the clients stream
if (stream.DataAvailable)
{
//gets the type of request sent by the client
byte reqType = reader.ReadByte();
switch (reqType)
{
//request for chat server
case 1:
//locks to ensure server counter not modified by another thread
lock (serverCounterLock)
{
//increments server counter
serverCounter++;
//creates chat server with serverCounter as its ID in new thread
Thread tC = new Thread(startChatServer);
tC.Start(serverCounter);
//writes the assigned serverID to client
writer.Write(serverCounter);
}
break;
//request for resource server
case 2:
//locks to ensure server counter not modified by another thread
lock (serverCounterLock)
{
//increments server counter
serverCounter++;
//creates resource server with serverCounter as its ID in new thread
Thread tR = new Thread(startResourceServer);
tR.Start(serverCounter);
//writes the assigned serverID to client
writer.Write(serverCounter);
}
break;
//request for real time collaboration server
case 3:
//locks to ensure server counter not modified by another thread
lock (serverCounterLock)
{
//increments server counter
serverCounter++;
//creates real time collaboration server with serverCounter as its ID in new thread
Thread tRTC = new Thread(startRTCServer);
tRTC.Start(serverCounter);
//writes the assigned serverID to client
writer.Write(serverCounter);
}
break;
//request to connect a client to a server
case 4:
TcpClient connect;
//reads connection info from stream
byte serType = reader.ReadByte();
uint serverID = reader.ReadUInt32();
uint clientID = reader.ReadUInt32();
//checks if specified client connected, and gets corresponding TcpClient
if (clientList.TryGetValue(clientID, out connect))
{
//creates reader and writer on requested clients stream
NetworkStream cStream = connect.GetStream();
BinaryWriter cWriter = new BinaryWriter(cStream);
//indicates whether client successfully connected
bool success = false;
//checks the type of server connection request for
switch (serType)
{
//connection request for chat server
case 1:
//locks to ensure ChatServer's currentID is not changed
lock (ChatServer.IDLock)
{
//tells chat servers listener that incoming request is for server with specified ID
ChatServer.setCurrentID(serverID);
ChatServer.setExpectedClient(clientID);
//tells chat server that a connection is expected
ChatServer.connectExpected.Set();
//tells client to connect
cWriter.Write(serType);
cWriter.Write(serverID);
//waits for client to connect to unlock, connectExpected set to false when it does
success = ChatServer.connected.Wait(TimeSpan.FromSeconds(5));
//ensures values reset regardless of outcome
ChatServer.connectExpected.Reset();
ChatServer.connected.Reset();
}
break;
//connection request for resource server
case 2:
//structure same as chat server, see comments for case 1
lock (ResourceServer.IDLock)
{
ResourceServer.setCurrentID(serverID);
ResourceServer.setExpectedClient(clientID);
ResourceServer.connectExpected.Set();
cWriter.Write(serType);
cWriter.Write(serverID);
success = ResourceServer.connected.Wait(TimeSpan.FromSeconds(5));
//ensures values reset regardless of outcome
ResourceServer.connectExpected.Reset();
ResourceServer.connected.Reset();
}
break;
//connection request for real time collaboration server
case 3:
//structure same as chat server, see comments for case 1
lock (RTCServer.IDLock)
{
RTCServer.setCurrentID(serverID);
RTCServer.setExpectedClient(clientID);
RTCServer.connectExpected.Set();
cWriter.Write(serType);
cWriter.Write(serverID);
success = RTCServer.connected.Wait(TimeSpan.FromSeconds(5));
//ensures values reset regardless of outcome
RTCServer.connectExpected.Reset();
RTCServer.connected.Reset();
}
break;
}
//checks if requested client still connected
if (connect.Connected && success)
{
//tells requester client successfully connected if it is
writer.Write(true);
}
else
{
//else indicates connection unsuccessful
writer.Write(false);
}
}
//requested client not connected
else
{
//tells client connection request was unsuccessful
writer.Write(false);
}
break;
//request for status of indicated client
case 5:
TcpClient temp;
//checks if indicated client is in list of connected clients
if (clientList.TryGetValue(reader.ReadUInt32(), out temp))
{
//tells requester specified client is connected
writer.Write(true);
}
else
{
//tells requester specified client is not connected
writer.Write(false);
}
break;
}
}
}
//cleanup
if (writer != null) { writer.Close(); }
if (reader != null) { reader.Close(); }
//removes client from list of connected clients
lock (clientList)
{
TcpClient close;
if (clientList.TryGetValue(thisClientID, out close))
{
close.GetStream().Close();
close.Close();
clientList.Remove(thisClientID);
}
}
}
}
//starts a real time collaboration server with specidied serverID
private void startRTCServer(object serverID)
{
TCPServer server = new RTCServer((uint)serverID);
server.startServer();
}
//starts a resource server with specidied serverID
private void startResourceServer(object serverID)
{
TCPServer server = new ResourceServer((uint)serverID);
server.startServer();
}
//starts a chat server with specidied serverID
private void startChatServer(object serverID)
{
TCPServer server = new ChatServer((uint)serverID);
server.startServer();
}
//stops the main server
public override void stopServer()
{
if (listener != null) { listener.Stop(); }
running = false;
}
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Server_Application_Console
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hit Ctrl-C to exit.");
new MainServer().startServer().Wait();
}
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Server Application Console")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Server Application Console")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("6f2e490c-75f7-4e37-a14c-434ad48656bb")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,59 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Server_Application_Console
{
class RTCServer : TCPServer
{
private uint thisServerID;
public static readonly object IDLock = new object();
private static uint currentID = 0;
public static ManualResetEventSlim connectExpected = new ManualResetEventSlim(false);
public static ManualResetEventSlim connected = new ManualResetEventSlim(false);
private static uint expectedClient;
public RTCServer(uint serverID)
{
thisServerID = serverID;
}
/*
public static void setConnectExpected()
{
connectExpected = true;
}
public static bool getConnectExpected()
{
return connectExpected;
}
*/
public static uint getCurrentID()
{
return currentID;
}
public static void setCurrentID(uint ID)
{
currentID = ID;
}
public override Task startServer()
{
throw new NotImplementedException();
}
public override void stopServer()
{
throw new NotImplementedException();
}
public static void setExpectedClient(uint clientID)
{
expectedClient = clientID;
}
}
}

View File

@ -0,0 +1,58 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Server_Application_Console
{
class ResourceServer : TCPServer
{
private uint serverID;
public static ManualResetEventSlim connectExpected = new ManualResetEventSlim(false);
public static ManualResetEventSlim connected = new ManualResetEventSlim(false);
private static uint currentID;
public static readonly object IDLock = new object();
private static uint expectedClient;
public ResourceServer(uint serverID)
{
this.serverID = serverID;
}
/*
public static void setConnectExpected()
{
connectExpected = true;
}
public static bool getConnectExpected()
{
return connectExpected;
}
*/
public static uint getCurrentID()
{
return currentID;
}
public static void setCurrentID(uint ID)
{
currentID = ID;
}
public override Task startServer()
{
throw new NotImplementedException();
}
public override void stopServer()
{
throw new NotImplementedException();
}
public static void setExpectedClient(uint clientID)
{
expectedClient = clientID;
}
}
}

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{6F2E490C-75F7-4E37-A14C-434AD48656BB}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Server_Application_Console</RootNamespace>
<AssemblyName>Server Application Console</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ChatServer.cs" />
<Compile Include="MainServer.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ResourceServer.cs" />
<Compile Include="RTCServer.cs" />
<Compile Include="TCPServer.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Server_Application_Console
{
abstract class TCPServer
{
//starts the server for use with the specified project
abstract public Task startServer();
//stops the server
abstract public void stopServer();
}
}