mirror of https://github.com/PCSX2/pcsx2.git
Started working on the debugger. Prepared only the link between master and client app. Have to investigate on the changes in the PATH1 done by Jake.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4106 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
b3c90f21a6
commit
0d0778a5dd
|
@ -8,20 +8,36 @@ using System.Threading;
|
|||
using System.Diagnostics;
|
||||
using GSDumpGUI.Properties;
|
||||
using System.IO;
|
||||
using TCPLibrary.MessageBased.Core;
|
||||
|
||||
namespace GSDumpGUI
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
static public GSDumpGUI frmMain;
|
||||
static public TCPLibrary.MessageBased.Core.BaseMessageServer Server;
|
||||
static public List<TCPLibrary.MessageBased.Core.BaseMessageClientS> Clients;
|
||||
|
||||
static public TCPLibrary.MessageBased.Core.BaseMessageClient Client;
|
||||
static private Boolean ChangeIcon;
|
||||
static private GSDump dump;
|
||||
|
||||
[STAThread]
|
||||
static void Main(String[] args)
|
||||
{
|
||||
if (args.Length == 4)
|
||||
{
|
||||
try
|
||||
{
|
||||
Client = new TCPLibrary.MessageBased.Core.BaseMessageClient();
|
||||
Client.OnMessageReceived += new TCPLibrary.MessageBased.Core.BaseMessageClient.MessageReceivedHandler(Client_OnMessageReceived);
|
||||
Client.Connect("localhost", 9999);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Client = null;
|
||||
}
|
||||
|
||||
Thread thd = new Thread(new ThreadStart(delegate
|
||||
{
|
||||
while (true)
|
||||
|
@ -55,21 +71,101 @@ namespace GSDumpGUI
|
|||
Directory.SetCurrentDirectory(Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory + "GSDumpGSDXConfigs\\" + Path.GetFileName(DLLPath) + "\\"));
|
||||
if (Operation == "GSReplay")
|
||||
{
|
||||
GSDump dump = GSDump.LoadDump(DumpPath);
|
||||
dump = GSDump.LoadDump(DumpPath);
|
||||
wrap.Run(dump, Renderer);
|
||||
ChangeIcon = true;
|
||||
}
|
||||
else
|
||||
wrap.GSConfig();
|
||||
wrap.Unload();
|
||||
|
||||
if (Client != null)
|
||||
Client.Disconnect();
|
||||
}
|
||||
else
|
||||
{
|
||||
Clients = new List<TCPLibrary.MessageBased.Core.BaseMessageClientS>();
|
||||
|
||||
Server = new TCPLibrary.MessageBased.Core.BaseMessageServer();
|
||||
Server.OnClientMessageReceived += new BaseMessageServer.MessageReceivedHandler(Server_OnClientMessageReceived);
|
||||
Server.OnClientAfterConnect += new TCPLibrary.Core.Server.ConnectedHandler(Server_OnClientAfterConnect);
|
||||
Server.OnClientAfterDisconnected += new TCPLibrary.Core.Server.DisconnectedHandler(Server_OnClientAfterDisconnected);
|
||||
Server.Port = 9999;
|
||||
Server.Enabled = true;
|
||||
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
frmMain = new GSDumpGUI();
|
||||
Application.Run(frmMain);
|
||||
|
||||
Server.Enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void Server_OnClientAfterDisconnected(TCPLibrary.Core.Server server, TCPLibrary.Core.ClientS sender)
|
||||
{
|
||||
Clients.Remove((TCPLibrary.MessageBased.Core.BaseMessageClientS)sender);
|
||||
RefreshList();
|
||||
}
|
||||
|
||||
static void Server_OnClientMessageReceived(BaseMessageServer server, BaseMessageClientS sender, TCPMessage Mess)
|
||||
{
|
||||
switch (Mess.MessageType)
|
||||
{
|
||||
case MessageType.Connect:
|
||||
break;
|
||||
case MessageType.MaxUsers:
|
||||
break;
|
||||
case MessageType.SizeDump:
|
||||
frmMain.Invoke(new Action<object>(delegate(object e)
|
||||
{
|
||||
frmMain.txtDumpSize.Text = (((int)Mess.Parameters[0]) / 1024f / 1024f).ToString("F2");
|
||||
}), new object[] { null });
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Client_OnMessageReceived(TCPLibrary.Core.Client sender, TCPLibrary.MessageBased.Core.TCPMessage Mess)
|
||||
{
|
||||
switch (Mess.MessageType)
|
||||
{
|
||||
case TCPLibrary.MessageBased.Core.MessageType.Connect:
|
||||
break;
|
||||
case TCPLibrary.MessageBased.Core.MessageType.MaxUsers:
|
||||
break;
|
||||
case TCPLibrary.MessageBased.Core.MessageType.SizeDump:
|
||||
TCPMessage msg = new TCPMessage();
|
||||
msg.MessageType = MessageType.SizeDump;
|
||||
if (dump != null)
|
||||
msg.Parameters.Add(dump.Size);
|
||||
else
|
||||
msg.Parameters.Add(0);
|
||||
Client.Send(msg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Server_OnClientAfterConnect(TCPLibrary.Core.Server server, TCPLibrary.Core.ClientS sender)
|
||||
{
|
||||
Clients.Add((TCPLibrary.MessageBased.Core.BaseMessageClientS)sender);
|
||||
RefreshList();
|
||||
}
|
||||
|
||||
private static void RefreshList()
|
||||
{
|
||||
frmMain.Invoke(new Action<object>( delegate(object e)
|
||||
{
|
||||
frmMain.lstProcesses.Items.Clear();
|
||||
|
||||
foreach (var itm in Clients)
|
||||
{
|
||||
frmMain.lstProcesses.Items.Add(itm.IPAddress);
|
||||
}
|
||||
}), new object[] { null});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,12 @@
|
|||
this.rdaNone = new System.Windows.Forms.RadioButton();
|
||||
this.lblInternalLog = new System.Windows.Forms.Label();
|
||||
this.txtIntLog = new System.Windows.Forms.TextBox();
|
||||
this.lblDebugger = new System.Windows.Forms.Label();
|
||||
this.lstProcesses = new System.Windows.Forms.ListBox();
|
||||
this.lblChild = new System.Windows.Forms.Label();
|
||||
this.lblDumpSize = new System.Windows.Forms.Label();
|
||||
this.txtDumpSize = new System.Windows.Forms.Label();
|
||||
this.lblWIP = new System.Windows.Forms.Label();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pctBox)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
|
@ -303,11 +309,72 @@
|
|||
this.txtIntLog.TabIndex = 24;
|
||||
this.txtIntLog.TabStop = false;
|
||||
//
|
||||
// lblDebugger
|
||||
//
|
||||
this.lblDebugger.AutoSize = true;
|
||||
this.lblDebugger.Location = new System.Drawing.Point(417, 470);
|
||||
this.lblDebugger.Name = "lblDebugger";
|
||||
this.lblDebugger.Size = new System.Drawing.Size(54, 13);
|
||||
this.lblDebugger.TabIndex = 26;
|
||||
this.lblDebugger.Text = "Debugger";
|
||||
//
|
||||
// lstProcesses
|
||||
//
|
||||
this.lstProcesses.FormattingEnabled = true;
|
||||
this.lstProcesses.Location = new System.Drawing.Point(12, 502);
|
||||
this.lstProcesses.Name = "lstProcesses";
|
||||
this.lstProcesses.Size = new System.Drawing.Size(248, 251);
|
||||
this.lstProcesses.TabIndex = 27;
|
||||
this.lstProcesses.SelectedIndexChanged += new System.EventHandler(this.lstProcesses_SelectedIndexChanged);
|
||||
//
|
||||
// lblChild
|
||||
//
|
||||
this.lblChild.AutoSize = true;
|
||||
this.lblChild.Location = new System.Drawing.Point(9, 487);
|
||||
this.lblChild.Name = "lblChild";
|
||||
this.lblChild.Size = new System.Drawing.Size(82, 13);
|
||||
this.lblChild.TabIndex = 28;
|
||||
this.lblChild.Text = "Child Processes";
|
||||
//
|
||||
// lblDumpSize
|
||||
//
|
||||
this.lblDumpSize.AutoSize = true;
|
||||
this.lblDumpSize.Location = new System.Drawing.Point(279, 487);
|
||||
this.lblDumpSize.Name = "lblDumpSize";
|
||||
this.lblDumpSize.Size = new System.Drawing.Size(58, 13);
|
||||
this.lblDumpSize.TabIndex = 29;
|
||||
this.lblDumpSize.Text = "Dump Size";
|
||||
//
|
||||
// txtDumpSize
|
||||
//
|
||||
this.txtDumpSize.AutoSize = true;
|
||||
this.txtDumpSize.Location = new System.Drawing.Point(279, 502);
|
||||
this.txtDumpSize.Name = "txtDumpSize";
|
||||
this.txtDumpSize.Size = new System.Drawing.Size(0, 13);
|
||||
this.txtDumpSize.TabIndex = 30;
|
||||
//
|
||||
// lblWIP
|
||||
//
|
||||
this.lblWIP.AutoSize = true;
|
||||
this.lblWIP.Font = new System.Drawing.Font("Times New Roman", 48F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.lblWIP.ForeColor = System.Drawing.Color.Red;
|
||||
this.lblWIP.Location = new System.Drawing.Point(407, 589);
|
||||
this.lblWIP.Name = "lblWIP";
|
||||
this.lblWIP.Size = new System.Drawing.Size(508, 73);
|
||||
this.lblWIP.TabIndex = 31;
|
||||
this.lblWIP.Text = "Work in Progress";
|
||||
//
|
||||
// GSDumpGUI
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(988, 467);
|
||||
this.ClientSize = new System.Drawing.Size(988, 766);
|
||||
this.Controls.Add(this.lblWIP);
|
||||
this.Controls.Add(this.txtDumpSize);
|
||||
this.Controls.Add(this.lblDumpSize);
|
||||
this.Controls.Add(this.lstProcesses);
|
||||
this.Controls.Add(this.lblChild);
|
||||
this.Controls.Add(this.lblDebugger);
|
||||
this.Controls.Add(this.lblInternalLog);
|
||||
this.Controls.Add(this.txtIntLog);
|
||||
this.Controls.Add(this.rdaNone);
|
||||
|
@ -372,6 +439,12 @@
|
|||
private System.Windows.Forms.RadioButton rdaNone;
|
||||
private System.Windows.Forms.Label lblInternalLog;
|
||||
private System.Windows.Forms.TextBox txtIntLog;
|
||||
private System.Windows.Forms.Label lblDebugger;
|
||||
private System.Windows.Forms.Label lblChild;
|
||||
public System.Windows.Forms.ListBox lstProcesses;
|
||||
private System.Windows.Forms.Label lblDumpSize;
|
||||
public System.Windows.Forms.Label txtDumpSize;
|
||||
private System.Windows.Forms.Label lblWIP;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ using System.Runtime.InteropServices;
|
|||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
using System.Security;
|
||||
using TCPLibrary.MessageBased.Core;
|
||||
|
||||
namespace GSDumpGUI
|
||||
{
|
||||
|
@ -351,5 +352,15 @@ namespace GSDumpGUI
|
|||
Properties.Settings.Default.DumpDir = txtDumpsDirectory.Text;
|
||||
Properties.Settings.Default.Save();
|
||||
}
|
||||
|
||||
private void lstProcesses_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (lstProcesses.SelectedIndex != -1)
|
||||
{
|
||||
TCPMessage msg = new TCPMessage();
|
||||
msg.MessageType = MessageType.SizeDump;
|
||||
Program.Clients.Find(a => a.IPAddress == lstProcesses.SelectedItem.ToString()).Send(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,15 @@
|
|||
<Compile Include="Library\GSDXWrapper.cs" />
|
||||
<Compile Include="Library\NativeMethods.cs" />
|
||||
<Compile Include="Core\Program.cs" />
|
||||
<Compile Include="Library\TCPLibrary\Message\BaseMessageClient.cs" />
|
||||
<Compile Include="Library\TCPLibrary\Message\BaseMessageClientS.cs" />
|
||||
<Compile Include="Library\TCPLibrary\Message\BaseMessageServer.cs" />
|
||||
<Compile Include="Library\TCPLibrary\Base\CancelArgs.cs" />
|
||||
<Compile Include="Library\TCPLibrary\Base\Client.cs" />
|
||||
<Compile Include="Library\TCPLibrary\Base\ClientS.cs" />
|
||||
<Compile Include="Library\TCPLibrary\Base\Data.cs" />
|
||||
<Compile Include="Library\TCPLibrary\Base\Server.cs" />
|
||||
<Compile Include="Library\TCPLibrary\Message\TCPMessage.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<EmbeddedResource Include="Forms\frmMain.resx">
|
||||
<DependentUpon>frmMain.cs</DependentUpon>
|
||||
|
|
|
@ -186,52 +186,7 @@ namespace GSDumpGUI
|
|||
}
|
||||
foreach (var itm in dump.Data)
|
||||
{
|
||||
switch (itm.id)
|
||||
{
|
||||
case GSType.Transfer:
|
||||
switch (itm.data[0])
|
||||
{
|
||||
case 0:
|
||||
fixed (byte* gifdata = itm.data)
|
||||
{
|
||||
byte[] data = new byte[4];
|
||||
data[0]=*(gifdata+1);
|
||||
data[1]=*(gifdata+2);
|
||||
data[2]=*(gifdata+3);
|
||||
data[3]=*(gifdata+4);
|
||||
Int32 size = BitConverter.ToInt32(data, 0);
|
||||
GSgifTransfer1(new IntPtr(gifdata + 5), 16384 - size);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
fixed (byte* gifdata = itm.data)
|
||||
{
|
||||
GSgifTransfer2(new IntPtr(gifdata + 1), (itm.data.Length - 1) / 16);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
fixed (byte* gifdata = itm.data)
|
||||
{
|
||||
GSgifTransfer3(new IntPtr(gifdata + 1), (itm.data.Length - 1) / 16);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GSType.VSync:
|
||||
GSVSync(itm.data[0]);
|
||||
break;
|
||||
case GSType.ReadFIFO2:
|
||||
fixed (byte* FIFO = itm.data)
|
||||
{
|
||||
GSreadFIFO2(new IntPtr(FIFO), itm.data.Length / 16);
|
||||
}
|
||||
break;
|
||||
case GSType.Registers:
|
||||
Marshal.Copy(itm.data, 0, new IntPtr(pointer), 8192);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Step(itm, pointer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,6 +196,57 @@ namespace GSDumpGUI
|
|||
}
|
||||
}
|
||||
|
||||
private unsafe void Step(GSData itm, byte* registers)
|
||||
{
|
||||
switch (itm.id)
|
||||
{
|
||||
case GSType.Transfer:
|
||||
switch (itm.data[0])
|
||||
{/*
|
||||
case 0:
|
||||
byte[] data = new byte[16384];
|
||||
for (int i = 0; i < itm.data; i++)
|
||||
{
|
||||
|
||||
}
|
||||
fixed (byte* gifdata = data)
|
||||
{
|
||||
GSgifTransfer1(new IntPtr(gifdata + 5), 16384 - size);
|
||||
}
|
||||
break;*/
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
fixed (byte* gifdata = itm.data)
|
||||
{
|
||||
GSgifTransfer2(new IntPtr(gifdata + 1), (itm.data.Length - 1) / 16);
|
||||
}
|
||||
break;/*
|
||||
case 2:
|
||||
fixed (byte* gifdata = itm.data)
|
||||
{
|
||||
GSgifTransfer3(new IntPtr(gifdata + 1), (itm.data.Length - 1) / 16);
|
||||
}
|
||||
break;*/
|
||||
}
|
||||
break;
|
||||
case GSType.VSync:
|
||||
GSVSync(itm.data[0]);
|
||||
break;
|
||||
case GSType.ReadFIFO2:
|
||||
fixed (byte* FIFO = itm.data)
|
||||
{
|
||||
GSreadFIFO2(new IntPtr(FIFO), itm.data.Length / 16);
|
||||
}
|
||||
break;
|
||||
case GSType.Registers:
|
||||
Marshal.Copy(itm.data, 0, new IntPtr(registers), 8192);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
Running = false;
|
||||
|
|
|
@ -11,6 +11,22 @@ namespace GSDumpGUI
|
|||
public byte[] StateData;
|
||||
public byte[] Registers; // 8192 bytes
|
||||
|
||||
public int Size
|
||||
{
|
||||
get
|
||||
{
|
||||
int size = 0;
|
||||
size = 4;
|
||||
size += StateData.Length;
|
||||
size += Registers.Length;
|
||||
foreach (var itm in Data)
|
||||
{
|
||||
size += itm.data.Length;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
public List<GSData> Data;
|
||||
|
||||
public GSDump()
|
||||
|
@ -37,31 +53,12 @@ namespace GSDumpGUI
|
|||
{
|
||||
case GSType.Transfer:
|
||||
byte index = br.ReadByte();
|
||||
if (index == 0)
|
||||
{
|
||||
Int32 size = br.ReadInt32();
|
||||
Int32 size = br.ReadInt32();
|
||||
|
||||
byte[] dat = new byte[16384];
|
||||
List<byte> Data = new List<byte>();
|
||||
Data.Add(index);
|
||||
Data.AddRange(BitConverter.GetBytes(size));
|
||||
Data.AddRange(dat);
|
||||
|
||||
int startaddr = 16389 - size;
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
Data[startaddr + i] = br.ReadByte();
|
||||
data.data = Data.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
Int32 size = br.ReadInt32();
|
||||
|
||||
List<byte> Data = new List<byte>();
|
||||
Data.Add(index);
|
||||
Data.AddRange(br.ReadBytes(size));
|
||||
data.data = Data.ToArray();
|
||||
}
|
||||
List<byte> Data = new List<byte>();
|
||||
Data.Add(index);
|
||||
Data.AddRange(br.ReadBytes(size));
|
||||
data.data = Data.ToArray();
|
||||
break;
|
||||
case GSType.VSync:
|
||||
data.data = br.ReadBytes(1);
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2009 Ferreri Alessio
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace TCPLibrary.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for containing information regarding the acceptance of a determinate situation.
|
||||
/// </summary>
|
||||
public class CancelArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether the operation should be cancelled.
|
||||
/// </summary>
|
||||
private Boolean _cancel;
|
||||
/// <summary>
|
||||
/// Get/set the flag that determines if the operation should be cancelled.
|
||||
/// </summary>
|
||||
public Boolean Cancel
|
||||
{
|
||||
get { return _cancel; }
|
||||
set { _cancel = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base constructor of the class.
|
||||
/// </summary>
|
||||
/// <param name="cancel">Whether the operation should be cancelled.</param>
|
||||
public CancelArgs(Boolean cancel)
|
||||
{
|
||||
this._cancel = cancel;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,323 @@
|
|||
/*
|
||||
* Copyright (c) 2009 Ferreri Alessio
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
using System.ComponentModel;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace TCPLibrary.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Base TCP client class wrapped around TcpClient.
|
||||
/// </summary>
|
||||
public class Client
|
||||
{
|
||||
/// <summary>
|
||||
/// Lock object to assure that certain operation over the socket class are executed
|
||||
/// in an exclusive way.
|
||||
/// </summary>
|
||||
private Object _lock;
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper around the Network Stream of the socket. (Read-Only)
|
||||
/// </summary>
|
||||
private BinaryReader tr;
|
||||
/// <summary>
|
||||
/// Wrapper around the Network Stream of the socket. (Write-Only)
|
||||
/// </summary>
|
||||
private BinaryWriter tw;
|
||||
/// <summary>
|
||||
/// Address to which the client is connected.
|
||||
/// </summary>
|
||||
private IPEndPoint _address;
|
||||
|
||||
/// <summary>
|
||||
/// Flag to permit thread exit from the external.
|
||||
/// </summary>
|
||||
protected Boolean _active;
|
||||
/// <summary>
|
||||
/// Socket maintaining the connection.
|
||||
/// </summary>
|
||||
protected TcpClient _socket;
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the address to which the client is connected.
|
||||
/// </summary>
|
||||
public IPEndPoint Address
|
||||
{
|
||||
get { return _address; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the state of the connection.
|
||||
/// </summary>
|
||||
public Boolean Connected
|
||||
{
|
||||
get { return _socket != null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for the event of receiving/sending a line of data from/to the server.
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender of the event.</param>
|
||||
/// <param name="Data">Line of data received.</param>
|
||||
public delegate void DataCommunicationHandler(Client sender, Data Data);
|
||||
/// <summary>
|
||||
/// Occurs when a line of data is received from the server.
|
||||
/// </summary>
|
||||
public event DataCommunicationHandler OnDataReceived;
|
||||
/// <summary>
|
||||
/// Occurs before the client send a line of data to the server.
|
||||
/// </summary>
|
||||
public event DataCommunicationHandler OnBeforeDataSent;
|
||||
/// <summary>
|
||||
/// Occurs after the client send a line of data to the server.
|
||||
/// </summary>
|
||||
public event DataCommunicationHandler OnAfterDataSent;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for the event of connection/disconnection to the server.
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender of the event.</param>
|
||||
public delegate void ConnectionStateHandler(Client sender);
|
||||
/// <summary>
|
||||
/// Occurs when the client successfully connect the server.
|
||||
/// </summary>
|
||||
public event ConnectionStateHandler OnConnected;
|
||||
/// <summary>
|
||||
/// Occurs when the client is disconnected from the server.
|
||||
/// </summary>
|
||||
public event ConnectionStateHandler OnDisconnected;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for the event of connection failed for rejection by the server.
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender of the event.</param>
|
||||
/// <param name="Message">Message of fail sent by the server.</param>
|
||||
public delegate void ConnectionFailedHandler(Client sender, byte[] Message);
|
||||
/// <summary>
|
||||
/// Occurs when the client failed to connect to the server because the server rejected the connection.
|
||||
/// </summary>
|
||||
public event ConnectionFailedHandler OnConnectFailed;
|
||||
|
||||
/// <summary>
|
||||
/// Base constructor of the class.
|
||||
/// </summary>
|
||||
public Client()
|
||||
{
|
||||
_lock = new object();
|
||||
_address = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to connect to the server specified.
|
||||
/// </summary>
|
||||
/// <param name="Indirizzo">Address of the server to connect.</param>
|
||||
/// <param name="Port">Port of the server to connect.</param>
|
||||
/// <returns>True if the connection is successfull, false otherwise.</returns>
|
||||
/// <exception cref="TCPLibrary.Core.AlreadyConnectedException" />
|
||||
/// <exception cref="System.Net.Sockets.SocketException" />
|
||||
public virtual Boolean Connect(String Indirizzo, Int32 Port)
|
||||
{
|
||||
if (!Connected)
|
||||
{
|
||||
IPHostEntry addr = Dns.GetHostEntry(Indirizzo);
|
||||
IPAddress ip = null;
|
||||
|
||||
foreach (var itm in addr.AddressList)
|
||||
{
|
||||
if (itm.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
ip = itm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ip != null)
|
||||
{
|
||||
_address = new IPEndPoint(ip, Port);
|
||||
_socket = new TcpClient();
|
||||
|
||||
try
|
||||
{
|
||||
_socket.Connect(_address);
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
_socket = null;
|
||||
_address = null;
|
||||
throw;
|
||||
}
|
||||
|
||||
tr = new BinaryReader(_socket.GetStream());
|
||||
tw = new BinaryWriter(_socket.GetStream());
|
||||
|
||||
// Receive the confirmation of the status of the connection to the server.
|
||||
// Is CONNECTEDTCPSERVER if the connection is successfull, all other cases are wrong.
|
||||
|
||||
Int32 Length = Convert.ToInt32(tr.ReadInt32());
|
||||
byte[] arr = new byte[Length];
|
||||
tr.Read(arr, 0, Length);
|
||||
ASCIIEncoding ae = new ASCIIEncoding();
|
||||
String Accept = ae.GetString(arr, 0, arr.Length);
|
||||
|
||||
if (Accept == "CONNECTEDTCPSERVER")
|
||||
{
|
||||
_active = true;
|
||||
|
||||
Thread thd = new Thread(new ThreadStart(MainThread));
|
||||
thd.IsBackground = true;
|
||||
thd.Name = "Client connected to " + Indirizzo + ":" + Port.ToString();
|
||||
thd.Start();
|
||||
|
||||
if (OnConnected != null)
|
||||
OnConnected(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Stop();
|
||||
if (OnConnectFailed != null)
|
||||
OnConnectFailed(this, arr);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
throw new ArgumentException("The client is already connected!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disconnect a Client if connected.
|
||||
/// </summary>
|
||||
public virtual void Disconnect()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_active = false;
|
||||
tr.Close();
|
||||
tw.Close();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disconnect a Client if connected.
|
||||
/// </summary>
|
||||
protected virtual void Stop()
|
||||
{
|
||||
if (_socket != null)
|
||||
{
|
||||
tr.Close();
|
||||
tw.Close();
|
||||
_socket.Close();
|
||||
|
||||
_socket = null;
|
||||
_address = null;
|
||||
|
||||
if (OnDisconnected != null)
|
||||
OnDisconnected(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Thread function that actually run the socket work.
|
||||
/// </summary>
|
||||
private void MainThread()
|
||||
{
|
||||
while (_active)
|
||||
{
|
||||
byte[] arr = null;
|
||||
|
||||
try
|
||||
{
|
||||
int length = Convert.ToInt32(tr.ReadInt32());
|
||||
arr = new byte[length];
|
||||
int index = 0;
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
|
||||
int receivedBytes = tr.Read(arr, index, length);
|
||||
length -= receivedBytes;
|
||||
index += receivedBytes;
|
||||
}
|
||||
}
|
||||
catch (Exception) { }
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_active)
|
||||
{
|
||||
Boolean Stato = _socket.Client.Poll(100, SelectMode.SelectRead);
|
||||
if ((arr == null) && (Stato == true))
|
||||
break;
|
||||
else
|
||||
if (OnDataReceived != null)
|
||||
OnDataReceived(this, new Data(arr));
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
Stop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a line of data to the server.
|
||||
/// </summary>
|
||||
/// <param name="msg">Data to send to the server.</param>
|
||||
/// <exception cref="TCPLibrary.Core.NotConnectedException" />
|
||||
public void Send(Data msg)
|
||||
{
|
||||
if (_active)
|
||||
{
|
||||
if (OnBeforeDataSent != null)
|
||||
OnBeforeDataSent(this, msg);
|
||||
try
|
||||
{
|
||||
tw.Write(msg.Message.Length);
|
||||
tw.Write(msg.Message);
|
||||
tw.Flush();
|
||||
|
||||
if (OnAfterDataSent != null)
|
||||
OnAfterDataSent(this, msg);
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
// Pensare a cosa fare quà. Questo è il caso in cui il server ha chiuso forzatamente
|
||||
// la connessione mentre il client mandava roba.
|
||||
}
|
||||
}
|
||||
else
|
||||
throw new ArgumentException("The link is closed. Unable to send data.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* Copyright (c) 2009 Ferreri Alessio
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace TCPLibrary.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class that manages the single connection between a client and the server.
|
||||
/// </summary>
|
||||
public class ClientS
|
||||
{
|
||||
/// <summary>
|
||||
/// Lock object to assure that certain operation over the socket class are executed
|
||||
/// in an exclusive way.
|
||||
/// </summary>
|
||||
private Object _lock;
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper around the Network Stream of the socket. (Read-Only)
|
||||
/// </summary>
|
||||
private BinaryReader tr;
|
||||
/// <summary>
|
||||
/// Wrapper around the Network Stream of the socket. (Write-Only)
|
||||
/// </summary>
|
||||
private BinaryWriter tw;
|
||||
/// <summary>
|
||||
/// Current IP address of the client.
|
||||
/// </summary>
|
||||
private String _ipaddress;
|
||||
|
||||
/// <summary>
|
||||
/// Flag to permit thread exit from the external.
|
||||
/// </summary>
|
||||
protected Boolean _active;
|
||||
/// <summary>
|
||||
/// Link to the server to which this client is connected.
|
||||
/// </summary>
|
||||
protected Server _server;
|
||||
/// <summary>
|
||||
/// Actual socket of the client.
|
||||
/// </summary>
|
||||
protected TcpClient _client;
|
||||
|
||||
/// <summary>
|
||||
/// Get the state of the connection.
|
||||
/// </summary>
|
||||
public Boolean Connected
|
||||
{
|
||||
get { return _client != null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// IP Address of the client.
|
||||
/// </summary>
|
||||
public String IPAddress
|
||||
{
|
||||
get { return _ipaddress; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base class constructor.
|
||||
/// </summary>
|
||||
/// <param name="server">Server to which this client is linked to.</param>
|
||||
/// <param name="client">Socket of the client.</param>
|
||||
protected internal ClientS(Server server, TcpClient client)
|
||||
{
|
||||
_lock = new object();
|
||||
|
||||
_active = true;
|
||||
_server = server;
|
||||
_client = client;
|
||||
_ipaddress = _client.Client.RemoteEndPoint.ToString();
|
||||
|
||||
NetworkStream ns = _client.GetStream();
|
||||
tr = new BinaryReader(ns);
|
||||
tw = new BinaryWriter(ns);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start up the thread managing this Client-Server connection.
|
||||
/// </summary>
|
||||
protected internal virtual void Start()
|
||||
{
|
||||
Thread _thread = new Thread(new ThreadStart(MainThread));
|
||||
_thread.IsBackground = true;
|
||||
_thread.Name = "Thread Client " + _ipaddress;
|
||||
_thread.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Thread function that actually run the socket work.
|
||||
/// </summary>
|
||||
private void MainThread()
|
||||
{
|
||||
while (_active)
|
||||
{
|
||||
byte[] arr = null;
|
||||
|
||||
try
|
||||
{
|
||||
int length = Convert.ToInt32(tr.ReadInt32());
|
||||
arr = new byte[length];
|
||||
int index = 0;
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
|
||||
int receivedBytes = tr.Read(arr, index, length);
|
||||
length -= receivedBytes;
|
||||
index += receivedBytes;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine(ex.ToString());
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_active)
|
||||
{
|
||||
Boolean Stato = _client.Client.Poll(100, SelectMode.SelectRead);
|
||||
if ((arr == null) && (Stato == true))
|
||||
break;
|
||||
else
|
||||
_server.RaiseDataReceivedEvent(this, new Data(arr));
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
Stop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a line of data to the client.
|
||||
/// </summary>
|
||||
/// <param name="Data">Data to send to the client.</param>
|
||||
/// <exception cref="TCPLibrary.Core.NotConnectedException" />
|
||||
public void Send(Data Data)
|
||||
{
|
||||
if (_active)
|
||||
{
|
||||
_server.RaiseBeforeDataSentEvent(this, Data);
|
||||
|
||||
try
|
||||
{
|
||||
tw.Write(Data.Message.Length);
|
||||
tw.Write(Data.Message);
|
||||
tw.Flush();
|
||||
|
||||
_server.RaiseAfterDataSentEvent(this, Data);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.Write(ex.ToString());
|
||||
// Pensare a cosa fare quà. Questo è il caso in cui il client ha chiuso forzatamente
|
||||
// la connessione mentre il server mandava roba.
|
||||
}
|
||||
}
|
||||
else
|
||||
throw new ArgumentException("The link is closed. Unable to send data.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close the link between Client e Server.
|
||||
/// </summary>
|
||||
public void Disconnect()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_active = false;
|
||||
tr.Close();
|
||||
tw.Close();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close the link between Client e Server.
|
||||
/// </summary>
|
||||
protected internal void Stop()
|
||||
{
|
||||
if (_client != null)
|
||||
{
|
||||
_server.RaiseClientBeforeDisconnectedEvent(this);
|
||||
|
||||
tr.Close();
|
||||
tw.Close();
|
||||
|
||||
_client.Close();
|
||||
_client = null;
|
||||
|
||||
lock (_server.Clients)
|
||||
{
|
||||
_server.Clients.Remove(this);
|
||||
}
|
||||
|
||||
_server.RaiseClientAfterDisconnectedEvent(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2009 Ferreri Alessio
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace TCPLibrary.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Structure for containing the data to be sent over a base client/server
|
||||
/// </summary>
|
||||
public class Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Data to be sent.
|
||||
/// </summary>
|
||||
private byte[] _message;
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the data to be sent.
|
||||
/// </summary>
|
||||
public byte[] Message
|
||||
{
|
||||
get { return _message; }
|
||||
set { _message = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base constructor of the class.
|
||||
/// </summary>
|
||||
/// <param name="msg">Data to be sent.</param>
|
||||
public Data(byte[] msg)
|
||||
{
|
||||
this._message = msg;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,365 @@
|
|||
/*
|
||||
* Copyright (c) 2009 Ferreri Alessio
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
using System.ComponentModel;
|
||||
using System.Text;
|
||||
|
||||
namespace TCPLibrary.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Base TCP server class wrapped around TcpListener.
|
||||
/// </summary>
|
||||
public class Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Socket maintaining the connection.
|
||||
/// </summary>
|
||||
private TcpListener _socket;
|
||||
/// <summary>
|
||||
/// Port to which the server will listen.
|
||||
/// </summary>
|
||||
private Int32 _port;
|
||||
/// <summary>
|
||||
/// Whether the server is enabled or not.
|
||||
/// </summary>
|
||||
private Boolean _enabled;
|
||||
/// <summary>
|
||||
/// List of the clients connected to the server.
|
||||
/// </summary>
|
||||
private List<ClientS> _clients;
|
||||
/// <summary>
|
||||
/// Number of connection permitted in the backlog of the server.
|
||||
/// </summary>
|
||||
private Int32 _connectionbacklog;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for the event of the Enabled property change.
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender of the event.</param>
|
||||
public delegate void EnabledChangedHandler(Server sender);
|
||||
/// <summary>
|
||||
/// Occurs when the Enabled property is changed.
|
||||
/// </summary>
|
||||
public event EnabledChangedHandler OnEnabledChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for the event of receiving a line of data from a client.
|
||||
/// </summary>
|
||||
/// <param name="server">Server raising the event.</param>
|
||||
/// <param name="client">Client involved in the communication.</param>
|
||||
/// <param name="Data">Line of data received.</param>
|
||||
public delegate void DataCommunicationHandler(Server server, ClientS client, Data Data);
|
||||
/// <summary>
|
||||
/// Occurs when a client send a line of data to the server.
|
||||
/// </summary>
|
||||
public event DataCommunicationHandler OnClientDataReceived;
|
||||
/// <summary>
|
||||
/// Occurs before the server send a line of data to a client.
|
||||
/// </summary>
|
||||
public event DataCommunicationHandler OnClientBeforeDataSent;
|
||||
/// <summary>
|
||||
/// Occurs after the server send a line of data to a client.
|
||||
/// </summary>
|
||||
public event DataCommunicationHandler OnClientAfterDataSent;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for the event of a connection of a client.
|
||||
/// </summary>
|
||||
/// <param name="server">Server raising the event.</param>
|
||||
/// <param name="sender">The new client connected.</param>
|
||||
public delegate void ConnectedHandler(Server server, ClientS sender);
|
||||
/// <summary>
|
||||
/// Occurs after a client is connected to the server.
|
||||
/// </summary>
|
||||
public event ConnectedHandler OnClientAfterConnect;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for the event of a connection of a client.
|
||||
/// </summary>
|
||||
/// <param name="server">Server raising the event.</param>
|
||||
/// <param name="client">The new client to be connected.</param>
|
||||
/// <param name="args">Specify if the client should be accepted into the server.</param>
|
||||
public delegate void BeforeConnectedHandler(Server server, ClientS client, CancelArgs args);
|
||||
/// <summary>
|
||||
/// Occurs before a client is allowed to connect to the server.
|
||||
/// </summary>
|
||||
public event BeforeConnectedHandler OnClientBeforeConnect;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for the event of disconnection of a client.
|
||||
/// </summary>
|
||||
/// <param name="server">Server raising the event.</param>
|
||||
/// <param name="sender">The client disconnected.</param>
|
||||
public delegate void DisconnectedHandler(Server server, ClientS sender);
|
||||
/// <summary>
|
||||
/// Occurs right after a client disconnect from the server.
|
||||
/// </summary>
|
||||
public event DisconnectedHandler OnClientAfterDisconnected;
|
||||
/// <summary>
|
||||
/// Occurs before a client disconnect from the server.
|
||||
/// </summary>
|
||||
public event DisconnectedHandler OnClientBeforeDisconnected;
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the port number to which the server will listen. Cannot be set while the server is active.
|
||||
/// </summary>
|
||||
/// <exception cref="TCPLibrary.Core.ServerAttivoException" />
|
||||
public Int32 Port
|
||||
{
|
||||
get { return _port; }
|
||||
set
|
||||
{
|
||||
if (Enabled == false)
|
||||
_port = value;
|
||||
else
|
||||
throw new ArgumentException("Impossibile eseguire l'operazione a server attivo");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the enabled state of the server. Setting this to true will actually activate the server.
|
||||
/// </summary>
|
||||
/// <exception cref="System.Net.Sockets.SocketException" />
|
||||
public Boolean Enabled
|
||||
{
|
||||
get { return _enabled; }
|
||||
set
|
||||
{
|
||||
if (value == true)
|
||||
{
|
||||
if (_enabled == false)
|
||||
ActivateServer();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_enabled == true)
|
||||
DeactivateServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the number of connection permitted in the backlog of the server.
|
||||
/// </summary>
|
||||
/// <exception cref="TCPLibrary.Core.ServerAttivoException" />
|
||||
public Int32 ConnectionBackLog
|
||||
{
|
||||
get { return _connectionbacklog; }
|
||||
set
|
||||
{
|
||||
if (Enabled == false)
|
||||
_connectionbacklog = value;
|
||||
else
|
||||
throw new ArgumentException("Impossibile eseguire l'operazione a server attivo");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the list of the clients connected to the server.
|
||||
/// </summary>
|
||||
public List<ClientS> Clients
|
||||
{
|
||||
get { return _clients; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deactivate the server.
|
||||
/// </summary>
|
||||
protected virtual void DeactivateServer()
|
||||
{
|
||||
_enabled = false;
|
||||
_socket.Stop();
|
||||
_socket = null;
|
||||
|
||||
lock (_clients)
|
||||
{
|
||||
for (int i = 0; i < _clients.Count; i++)
|
||||
_clients[i].Disconnect();
|
||||
}
|
||||
|
||||
if (OnEnabledChanged != null)
|
||||
OnEnabledChanged(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activate the server.
|
||||
/// </summary>
|
||||
protected virtual void ActivateServer()
|
||||
{
|
||||
_socket = new TcpListener(IPAddress.Any, Port);
|
||||
_socket.Start(ConnectionBackLog);
|
||||
Thread thd = new Thread(new ThreadStart(MainThread));
|
||||
thd.Name = "Server on port " + Port.ToString();
|
||||
thd.IsBackground = true;
|
||||
thd.Start();
|
||||
_enabled = true;
|
||||
if (OnEnabledChanged != null)
|
||||
OnEnabledChanged(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Broadcast a line of data to all the clients connected to the server.
|
||||
/// </summary>
|
||||
/// <param name="Data">Line of data to be sent.</param>
|
||||
/// <exception cref="TCPLibrary.Core.ServerNonAttivoException" />
|
||||
public void Broadcast(Data Data)
|
||||
{
|
||||
if (Enabled)
|
||||
{
|
||||
lock (_clients)
|
||||
{
|
||||
foreach (var itm in _clients)
|
||||
if (itm.Connected)
|
||||
itm.Send(Data);
|
||||
}
|
||||
}
|
||||
else
|
||||
throw new ArgumentException("Unable to execute this operation when the server is inactive.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base constructor of the class.
|
||||
/// </summary>
|
||||
public Server()
|
||||
{
|
||||
_clients = new List<ClientS>();
|
||||
_port = 0;
|
||||
_connectionbacklog = 0;
|
||||
_enabled = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Thread function that actually run the server socket work.
|
||||
/// </summary>
|
||||
private void MainThread()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (Enabled == true)
|
||||
{
|
||||
TcpClient client = _socket.AcceptTcpClient();
|
||||
|
||||
CancelArgs args = new CancelArgs(false);
|
||||
ClientS cl = CreateClient(client);
|
||||
if (OnClientBeforeConnect != null)
|
||||
OnClientBeforeConnect(this, cl, args);
|
||||
|
||||
if (args.Cancel != true)
|
||||
{
|
||||
lock (_clients)
|
||||
{
|
||||
_clients.Add(cl);
|
||||
}
|
||||
|
||||
ASCIIEncoding ae = new ASCIIEncoding();
|
||||
byte[] arr = ae.GetBytes("CONNECTEDTCPSERVER");
|
||||
|
||||
cl.Send(new Data(arr));
|
||||
|
||||
if (OnClientAfterConnect != null)
|
||||
OnClientAfterConnect(this, cl);
|
||||
cl.Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
client.GetStream().Close();
|
||||
client.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
Enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overridable function that create the structure to memorize the client data.
|
||||
/// </summary>
|
||||
/// <param name="socket">Socket of the client.</param>
|
||||
/// <returns>The structure in which memorize all the information of the client.</returns>
|
||||
protected virtual ClientS CreateClient(TcpClient socket)
|
||||
{
|
||||
ClientS cl = new ClientS(this, socket);
|
||||
return cl;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raise the OnClientAfterDataSent event.
|
||||
/// </summary>
|
||||
/// <param name="cl">Client that raised the event.</param>
|
||||
/// <param name="data">Line of data sent.</param>
|
||||
internal void RaiseAfterDataSentEvent(ClientS cl, Data data)
|
||||
{
|
||||
if (OnClientAfterDataSent != null)
|
||||
OnClientAfterDataSent(this, cl, data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raise the OnClientBeforeDataSent event.
|
||||
/// </summary>
|
||||
/// <param name="cl">Client that raised the event.</param>
|
||||
/// <param name="data">Line of data sent.</param>
|
||||
internal void RaiseBeforeDataSentEvent(ClientS cl, Data data)
|
||||
{
|
||||
if (OnClientBeforeDataSent != null)
|
||||
OnClientBeforeDataSent(this, cl, data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raise the OnDataReceived event.
|
||||
/// </summary>
|
||||
/// <param name="cl">Client that raised the event.</param>
|
||||
/// <param name="data">Line of data received.</param>
|
||||
internal void RaiseDataReceivedEvent(ClientS cl, Data data)
|
||||
{
|
||||
if (OnClientDataReceived != null)
|
||||
OnClientDataReceived(this, cl, data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raise the OnClientAfterDisconnected event.
|
||||
/// </summary>
|
||||
/// <param name="cl">Client that raised the event.</param>
|
||||
internal void RaiseClientAfterDisconnectedEvent(ClientS cl)
|
||||
{
|
||||
if (OnClientAfterDisconnected != null)
|
||||
OnClientAfterDisconnected(this, cl);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raise the OnClientBeforeDisconnected event.
|
||||
/// </summary>
|
||||
/// <param name="cl">Client that raised the event.</param>
|
||||
internal void RaiseClientBeforeDisconnectedEvent(ClientS cl)
|
||||
{
|
||||
if (OnClientBeforeDisconnected != null)
|
||||
OnClientBeforeDisconnected(this, cl);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2008 Ferreri Alessio
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using TCPLibrary.MessageBased.Core;
|
||||
using TCPLibrary.Core;
|
||||
using System;
|
||||
|
||||
namespace TCPLibrary.MessageBased.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// TCP Client Class that work with Message structures.
|
||||
/// </summary>
|
||||
public class BaseMessageClient : Client
|
||||
{
|
||||
/// <summary>
|
||||
/// Delegate for the event of receiving a message structure from the server.
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender of the event.</param>
|
||||
/// <param name="Mess">Message received.</param>
|
||||
public delegate void MessageReceivedHandler(Client sender, TCPMessage Mess);
|
||||
/// <summary>
|
||||
/// Occurs when the client receive a message structure from the server.
|
||||
/// </summary>
|
||||
public event MessageReceivedHandler OnMessageReceived;
|
||||
/// <summary>
|
||||
/// Delegate for the event of sending a message structure to the server.
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender of the event.</param>
|
||||
/// <param name="Mess">Message sent.</param>
|
||||
public delegate void MessageSentHandler(Client sender, TCPMessage Mess);
|
||||
/// <summary>
|
||||
/// Occurs before the client send a message structure to the server.
|
||||
/// </summary>
|
||||
public event MessageSentHandler OnBeforeMessageSent;
|
||||
/// <summary>
|
||||
/// Occurs after the client send a message structure to the server.
|
||||
/// </summary>
|
||||
public event MessageSentHandler OnAfterMessageSent;
|
||||
/// <summary>
|
||||
/// Delegate for the event of connection fail for max users number reached.
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender of the event.</param>
|
||||
public delegate void MaxUsersReached(Client sender);
|
||||
/// <summary>
|
||||
/// Occurs when the connection fail as the server reached the maximum number of clients allowed.
|
||||
/// </summary>
|
||||
public event MaxUsersReached OnMaxUsersConnectionFail;
|
||||
|
||||
/// <summary>
|
||||
/// Base constructor of the class.
|
||||
/// </summary>
|
||||
public BaseMessageClient()
|
||||
{
|
||||
OnDataReceived += new DataCommunicationHandler(BaseMessageClient_OnDataReceived);
|
||||
OnAfterDataSent += new DataCommunicationHandler(BaseMessageClient_OnDataSent);
|
||||
OnConnectFailed += new ConnectionFailedHandler(BaseMessageClient_OnConnectFailed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When the connection is rejected by the server raise the correct event.
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender of the event.</param>
|
||||
/// <param name="Message">Message of the server.</param>
|
||||
void BaseMessageClient_OnConnectFailed(Client sender, byte[] Message)
|
||||
{
|
||||
if (TCPLibrary.MessageBased.Core.TCPMessage.FromByteArray(Message).MessageType == MessageType.MaxUsers)
|
||||
if (OnMaxUsersConnectionFail != null)
|
||||
OnMaxUsersConnectionFail(sender);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse the raw data sent to the server and create Message structures.
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender of the event.</param>
|
||||
/// <param name="Data">Line of data sent.</param>
|
||||
void BaseMessageClient_OnDataSent(Client sender, Data Data)
|
||||
{
|
||||
TCPMessage msg = TCPMessage.FromByteArray(Data.Message);
|
||||
if (OnAfterMessageSent != null)
|
||||
OnAfterMessageSent(sender, msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse the raw data received from the server and create Message structures.
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender of the event.</param>
|
||||
/// <param name="Data">Line of data received.</param>
|
||||
void BaseMessageClient_OnDataReceived(Client sender, Data Data)
|
||||
{
|
||||
TCPMessage msg = null;
|
||||
try
|
||||
{
|
||||
msg = TCPMessage.FromByteArray(Data.Message);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
}
|
||||
if (msg != null)
|
||||
if (OnMessageReceived != null)
|
||||
OnMessageReceived(sender, msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a message structure to the server.
|
||||
/// </summary>
|
||||
/// <param name="msg">Message structure to be send.</param>
|
||||
/// <exception cref="TCPLibrary.Core.NotConnectedException"></exception>
|
||||
public void Send(TCPMessage msg)
|
||||
{
|
||||
if (OnBeforeMessageSent != null)
|
||||
OnBeforeMessageSent(this, msg);
|
||||
base.Send(new Data(msg.ToByteArray()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2008 Ferreri Alessio
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System.Net.Sockets;
|
||||
using TCPLibrary.Core;
|
||||
using TCPLibrary.MessageBased.Core;
|
||||
|
||||
namespace TCPLibrary.MessageBased.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that manages the single connection between a client and the server based
|
||||
/// on Message structures.
|
||||
/// </summary>
|
||||
public class BaseMessageClientS : ClientS
|
||||
{
|
||||
/// <summary>
|
||||
/// Base constructor of the class.
|
||||
/// </summary>
|
||||
/// <param name="server">Server to which this client is linked to.</param>
|
||||
/// <param name="client">Socket of the client.</param>
|
||||
protected internal BaseMessageClientS(Server server, TcpClient client)
|
||||
: base(server, client)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a Message structure to the client.
|
||||
/// </summary>
|
||||
/// <param name="msg">Message to be sent.</param>
|
||||
/// <exception cref="TCPLibrary.Core.NotConnectedException" />
|
||||
public void Send(TCPMessage msg)
|
||||
{
|
||||
((BaseMessageServer)_server).RaiseBeforeMessageSentEvent(this, msg);
|
||||
base.Send(new Data(msg.ToByteArray()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2008 Ferreri Alessio
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using TCPLibrary.MessageBased.Core;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using TCPLibrary.Core;
|
||||
|
||||
namespace TCPLibrary.MessageBased.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// TCP Server Class that work with Message structures.
|
||||
/// </summary>
|
||||
public class BaseMessageServer : Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Limit of user allowed inside the server.
|
||||
/// </summary>
|
||||
protected Int32 _userlimit;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for the event of receiving a Message from a client.
|
||||
/// </summary>
|
||||
/// <param name="server">Server raising the event.</param>
|
||||
/// <param name="sender">Client sending the message.</param>
|
||||
/// <param name="Mess">Message received.</param>
|
||||
public delegate void MessageReceivedHandler(BaseMessageServer server, BaseMessageClientS sender, TCPMessage Mess);
|
||||
/// <summary>
|
||||
/// Occurs when a Message is received by the server.
|
||||
/// </summary>
|
||||
public event MessageReceivedHandler OnClientMessageReceived;
|
||||
/// <summary>
|
||||
/// Delegate for the event of sending a Message to a client.
|
||||
/// </summary>
|
||||
/// <param name="server">Server raising the event.</param>
|
||||
/// <param name="receiver">Client that will receive the message.</param>
|
||||
/// <param name="Mess">Message to be sent.</param>
|
||||
public delegate void MessageSentHandler(BaseMessageServer server, BaseMessageClientS receiver, TCPMessage Mess);
|
||||
/// <summary>
|
||||
/// Occurs when the server send a Message to a client.
|
||||
/// </summary>
|
||||
public event MessageSentHandler OnClientBeforeMessageSent;
|
||||
/// <summary>
|
||||
/// Occurs when the server send a Message to a client.
|
||||
/// </summary>
|
||||
public event MessageSentHandler OnClientAfterMessageSent;
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the limit of users allowed inside the server.
|
||||
/// </summary>
|
||||
public Int32 UserLimit
|
||||
{
|
||||
get { return _userlimit; }
|
||||
set { _userlimit = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base constructor of the class.
|
||||
/// </summary>
|
||||
public BaseMessageServer() : base()
|
||||
{
|
||||
OnClientBeforeConnect += new BeforeConnectedHandler(BaseMessageServer_OnClientBeforeConnect);
|
||||
OnClientDataReceived += new DataCommunicationHandler(BaseMessageServer_OnDataReceived);
|
||||
OnClientAfterDataSent += new DataCommunicationHandler(BaseMessageServer_OnDataSent);
|
||||
_userlimit = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Kick the client if the server reached the maximum allowed number of clients.
|
||||
/// </summary>
|
||||
/// <param name="server">Server raising the event.</param>
|
||||
/// <param name="client">Client connecting to the server.</param>
|
||||
/// <param name="args">Specify if the client should be accepted into the server.</param>
|
||||
void BaseMessageServer_OnClientBeforeConnect(Server server, ClientS client, CancelArgs args)
|
||||
{
|
||||
if ((Clients.Count >= UserLimit) && (UserLimit != 0))
|
||||
{
|
||||
TCPMessage msg = new TCPMessage();
|
||||
msg.MessageType = MessageType.MaxUsers;
|
||||
((BaseMessageClientS)client).Send(msg);
|
||||
|
||||
args.Cancel = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trasform the line of data sent into a Message structure and raise
|
||||
/// the event linked.
|
||||
/// </summary>
|
||||
/// <param name="server">Server raising the event.</param>
|
||||
/// <param name="receiver">Client that will receive the Message.</param>
|
||||
/// <param name="Data">Line of data sent.</param>
|
||||
void BaseMessageServer_OnDataSent(Server server, ClientS receiver, Data Data)
|
||||
{
|
||||
TCPMessage msg = null;
|
||||
try
|
||||
{
|
||||
msg = TCPMessage.FromByteArray(Data.Message);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
}
|
||||
if (msg != null)
|
||||
if (OnClientAfterMessageSent != null)
|
||||
OnClientAfterMessageSent(this, (BaseMessageClientS)receiver, msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raise the OnClientBeforeMessageSent event.
|
||||
/// </summary>
|
||||
/// <param name="cl">Client that raised the event.</param>
|
||||
/// <param name="msg">Message to be sent.</param>
|
||||
internal void RaiseBeforeMessageSentEvent(ClientS cl, TCPMessage msg)
|
||||
{
|
||||
if (OnClientBeforeMessageSent != null)
|
||||
OnClientBeforeMessageSent(this, (BaseMessageClientS)cl, msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trasform the line of data received into a Message structure and raise
|
||||
/// the event linked.
|
||||
/// </summary>
|
||||
/// <param name="server">Server raising the event.</param>
|
||||
/// <param name="sender">Client sending the data.</param>
|
||||
/// <param name="Data">Line of data received.</param>
|
||||
void BaseMessageServer_OnDataReceived(Server server, ClientS sender, Data Data)
|
||||
{
|
||||
TCPMessage msg = null;
|
||||
try
|
||||
{
|
||||
msg = TCPMessage.FromByteArray(Data.Message);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
}
|
||||
if (msg != null)
|
||||
if (OnClientMessageReceived != null)
|
||||
OnClientMessageReceived(this, (BaseMessageClientS)sender, msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function that create the structure to memorize the client data.
|
||||
/// </summary>
|
||||
/// <param name="socket">Socket of the client.</param>
|
||||
/// <returns>The structure in which memorize all the information of the client.</returns>
|
||||
protected override ClientS CreateClient(TcpClient socket)
|
||||
{
|
||||
return new BaseMessageClientS(this, socket);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a message to all clients in broadcast.
|
||||
/// </summary>
|
||||
/// <param name="Data">Message to be sent.</param>
|
||||
public void Broadcast(TCPMessage Data)
|
||||
{
|
||||
base.Broadcast(new Data(Data.ToByteArray()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2008 Ferreri Alessio
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
namespace TCPLibrary.MessageBased.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Message structure that contains all the information of the message exchanged between
|
||||
/// Message driven server/client.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class TCPMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Message Type.
|
||||
/// </summary>
|
||||
private MessageType _messageType;
|
||||
/// <summary>
|
||||
/// Messages parameters.
|
||||
/// </summary>
|
||||
private List<object> _parameters;
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the message type.
|
||||
/// </summary>
|
||||
public MessageType MessageType
|
||||
{
|
||||
get { return _messageType; }
|
||||
set { _messageType = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the message parameters.
|
||||
/// </summary>
|
||||
public List<object> Parameters
|
||||
{
|
||||
get { return _parameters; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base constructor of the class.
|
||||
/// </summary>
|
||||
public TCPMessage()
|
||||
{
|
||||
_messageType = MessageType.Connect;
|
||||
_parameters = new List<object>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a string and create a Message structure.
|
||||
/// </summary>
|
||||
/// <param name="data">Raw data.</param>
|
||||
/// <returns>Parsed message structure.</returns>
|
||||
static public TCPMessage FromByteArray(byte[] data)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
BinaryWriter sw = new BinaryWriter(ms);
|
||||
sw.Write(data, 0, data.Length);
|
||||
sw.Flush();
|
||||
ms.Position = 0;
|
||||
|
||||
BinaryFormatter formatter = new BinaryFormatter();
|
||||
TCPMessage msg = formatter.Deserialize(ms) as TCPMessage;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trasform the structure into a String.
|
||||
/// </summary>
|
||||
/// <returns>The structure in a String format.</returns>
|
||||
public byte[] ToByteArray()
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
BinaryFormatter formatter = new BinaryFormatter();
|
||||
formatter.Serialize(ms, this);
|
||||
ms.Position = 0;
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public enum MessageType
|
||||
{
|
||||
Connect,
|
||||
MaxUsers,
|
||||
SizeDump
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue