2015-01-13 18:29:11 +00:00
|
|
|
|
using System;
|
2014-07-08 12:58:53 +00:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Net;
|
|
|
|
|
using System.Net.Sockets;
|
2015-01-13 18:29:11 +00:00
|
|
|
|
using xServer.Core.Packets;
|
2014-07-08 12:58:53 +00:00
|
|
|
|
|
2015-01-13 18:29:11 +00:00
|
|
|
|
namespace xServer.Core
|
2014-07-08 12:58:53 +00:00
|
|
|
|
{
|
|
|
|
|
public class Server
|
|
|
|
|
{
|
|
|
|
|
public long BytesReceived { get; set; }
|
|
|
|
|
public long BytesSent { get; set; }
|
|
|
|
|
|
|
|
|
|
public event ServerStateEventHandler ServerState;
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
public delegate void ServerStateEventHandler(Server s, bool listening);
|
|
|
|
|
|
|
|
|
|
private void OnServerState(bool listening)
|
|
|
|
|
{
|
|
|
|
|
if (ServerState != null)
|
|
|
|
|
{
|
|
|
|
|
ServerState(this, listening);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public event ClientStateEventHandler ClientState;
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
public delegate void ClientStateEventHandler(Server s, Client c, bool connected);
|
|
|
|
|
|
|
|
|
|
private void OnClientState(Client c, bool connected)
|
|
|
|
|
{
|
|
|
|
|
if (ClientState != null)
|
|
|
|
|
{
|
|
|
|
|
ClientState(this, c, connected);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public event ClientReadEventHandler ClientRead;
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
public delegate void ClientReadEventHandler(Server s, Client c, IPacket packet);
|
|
|
|
|
|
|
|
|
|
private void OnClientRead(Client c, IPacket packet)
|
|
|
|
|
{
|
|
|
|
|
if (ClientRead != null)
|
|
|
|
|
{
|
|
|
|
|
ClientRead(this, c, packet);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public event ClientWriteEventHandler ClientWrite;
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
public delegate void ClientWriteEventHandler(Server s, Client c, IPacket packet, long length);
|
|
|
|
|
|
|
|
|
|
private void OnClientWrite(Client c, IPacket packet, long length, byte[] rawData)
|
|
|
|
|
{
|
|
|
|
|
if (ClientWrite != null)
|
|
|
|
|
{
|
|
|
|
|
ClientWrite(this, c, packet, length);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Socket _handle;
|
|
|
|
|
private SocketAsyncEventArgs _item;
|
|
|
|
|
|
|
|
|
|
private bool Processing { get; set; }
|
|
|
|
|
|
|
|
|
|
public bool Listening { get; private set; }
|
|
|
|
|
|
|
|
|
|
private List<Client> _clients;
|
2015-04-21 18:27:52 +00:00
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
public Client[] Clients
|
|
|
|
|
{
|
2015-04-21 18:27:52 +00:00
|
|
|
|
get { return Listening ? _clients.ToArray() : new Client[0]; }
|
2014-07-08 12:58:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int ConnectedClients { get; set; }
|
2015-03-20 13:45:58 +00:00
|
|
|
|
public Dictionary<string, DateTime> AllTimeConnectedClients { get; set; }
|
2014-07-08 12:58:53 +00:00
|
|
|
|
|
|
|
|
|
private List<Type> PacketTypes { get; set; }
|
|
|
|
|
|
2015-03-31 16:15:48 +00:00
|
|
|
|
public Server()
|
2014-07-08 12:58:53 +00:00
|
|
|
|
{
|
|
|
|
|
PacketTypes = new List<Type>();
|
2015-03-20 13:45:58 +00:00
|
|
|
|
AllTimeConnectedClients = new Dictionary<string, DateTime>();
|
2014-07-08 12:58:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Listen(ushort port)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (!Listening)
|
|
|
|
|
{
|
|
|
|
|
_clients = new List<Client>();
|
|
|
|
|
|
|
|
|
|
_item = new SocketAsyncEventArgs();
|
|
|
|
|
_item.Completed += Process;
|
|
|
|
|
|
2015-04-07 16:27:56 +00:00
|
|
|
|
if (_handle != null)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
_handle.Close();
|
|
|
|
|
}
|
|
|
|
|
catch
|
2015-04-21 18:27:52 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
2015-04-07 16:27:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-07-08 12:58:53 +00:00
|
|
|
|
_handle = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
|
|
|
|
|
|
|
|
|
_handle.Bind(new IPEndPoint(IPAddress.Any, port));
|
|
|
|
|
_handle.Listen(1000);
|
|
|
|
|
|
|
|
|
|
Processing = false;
|
|
|
|
|
Listening = true;
|
|
|
|
|
|
|
|
|
|
OnServerState(true);
|
|
|
|
|
|
|
|
|
|
if (!_handle.AcceptAsync(_item))
|
|
|
|
|
Process(null, _item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception)
|
|
|
|
|
{
|
|
|
|
|
Disconnect();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Adds a Type to the serializer so a message can be properly serialized.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="parent">The parent type, i.e.: IPacket</param>
|
|
|
|
|
/// <param name="type">Type to be added</param>
|
|
|
|
|
public void AddTypeToSerializer(Type parent, Type type)
|
|
|
|
|
{
|
|
|
|
|
if (type == null || parent == null)
|
|
|
|
|
throw new ArgumentNullException();
|
|
|
|
|
|
|
|
|
|
PacketTypes.Add(type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void AddTypesToSerializer(Type parent, params Type[] types)
|
|
|
|
|
{
|
|
|
|
|
foreach (Type type in types)
|
|
|
|
|
AddTypeToSerializer(parent, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Process(object s, SocketAsyncEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (e.SocketError == SocketError.Success)
|
|
|
|
|
{
|
2015-03-31 16:15:48 +00:00
|
|
|
|
Client T = new Client(this, e.AcceptSocket, PacketTypes.ToArray());
|
2014-07-08 12:58:53 +00:00
|
|
|
|
|
|
|
|
|
lock (_clients)
|
|
|
|
|
{
|
|
|
|
|
_clients.Add(T);
|
|
|
|
|
T.ClientState += HandleState;
|
|
|
|
|
T.ClientRead += OnClientRead;
|
|
|
|
|
T.ClientWrite += OnClientWrite;
|
|
|
|
|
|
|
|
|
|
OnClientState(T, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
e.AcceptSocket = null;
|
|
|
|
|
if (!_handle.AcceptAsync(e))
|
|
|
|
|
Process(null, e);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
Disconnect();
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
Disconnect();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Disconnect()
|
|
|
|
|
{
|
|
|
|
|
if (Processing)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
Processing = true;
|
|
|
|
|
|
|
|
|
|
if (_handle != null)
|
|
|
|
|
_handle.Close();
|
|
|
|
|
|
|
|
|
|
lock (_clients)
|
|
|
|
|
{
|
|
|
|
|
while (_clients.Count != 0)
|
|
|
|
|
{
|
|
|
|
|
_clients[0].Disconnect();
|
2015-03-31 16:45:31 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
_clients.RemoveAt(0);
|
|
|
|
|
}
|
|
|
|
|
catch
|
2015-04-21 18:27:52 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
2014-07-08 12:58:53 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Listening = false;
|
|
|
|
|
OnServerState(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void HandleState(Client s, bool open)
|
|
|
|
|
{
|
|
|
|
|
lock (_clients)
|
|
|
|
|
{
|
|
|
|
|
_clients.Remove(s);
|
|
|
|
|
OnClientState(s, false);
|
2015-04-04 21:48:47 +00:00
|
|
|
|
|
|
|
|
|
s.Value.DisposeForms();
|
2014-07-08 12:58:53 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-04-21 18:27:52 +00:00
|
|
|
|
}
|