SocketClient
Code:
public class SocketClient
{
public SocketClient(Socket socket)
{
Socket = socket;
}
public Socket Socket;
public string IP
{
get
{
try
{
return (Socket.RemoteEndPoint as IPEndPoint).Address.ToString();
}
catch { return ""; }
}
}
public void Disconnect(bool reUse)
{
try
{
Socket.Close();
Socket.Disconnect(reUse);
}
catch (Exception e)
{
Server.ErrorHandler.Handle(e);
}
}
public byte[] Buffer;
public object Owner;
public string AuthAccount;
public string AuthPassword;
public PacketClient PacketClient;
public void EndAccept(Socket socket, IAsyncResult result)
{
Socket = socket.EndAccept(result);
}
public bool Connected
{
get { return Socket.Connected; }
}
public int EndReceive(IAsyncResult result, out SocketError SE)
{
return Socket.EndReceive(result, out SE);
}
public ConquerCryption Cryption;
}
Socket System:
Code:
public unsafe class ConquerSockets
{
Socket socket;
int port;
IPEndPoint IPE;
SocketInvoke InvokeHandler;
public ConquerSockets(int Port, SocketInvoke _InvokeHandler)
{
port = Port;
InvokeHandler = _InvokeHandler;
}
public void Listen()
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPE = new IPEndPoint(IPAddress.Any, port);
socket.Bind(IPE);
socket.Listen(100);
}
public void Accept()
{
socket.BeginAccept(new AsyncCallback(Accept), new SocketClient(null));
}
void Accept(IAsyncResult result)
{
try
{
SocketClient Client = result.AsyncState as SocketClient;
Client.Buffer = new byte[1024];
if (!Accepted(Client, result))
Accept();
InvokeHandler.Invoke(Client, ConquerServerProject.Enums.SocketInvokeType.Connection, null);
Accept();
Receive(Client);
}
catch { }
}
public void Receive(SocketClient Client)
{
Client.Socket.BeginReceive(Client.Buffer, 0, 1024, SocketFlags.None, new AsyncCallback(Receive), Client);
}
void Receive(IAsyncResult result)
{
SocketClient Client = null;
try
{
Client = result.AsyncState as SocketClient;
}
catch (Exception e) { Server.ErrorHandler.Handle(e); return; }
try
{
if (Client.Connected)
{
SocketError error;
int Len = Client.EndReceive(result, out error);
if (error == SocketError.Success)
{
if (Len > 0)
{
byte[] Received = new byte[Len];
MEMCPY(Received, Client.Buffer, Len);
InvokeHandler.Invoke(Client, Enums.SocketInvokeType.Receive, Received);
Receive(Client);
return;
}
}
}
InvokeHandler.Invoke(Client, Enums.SocketInvokeType.Disconnection, null);
}
catch
{
InvokeHandler.Invoke(Client, Enums.SocketInvokeType.Disconnection, null);
}
}
bool Accepted(SocketClient Client, IAsyncResult result)
{
try
{
Client.EndAccept(socket, result);
return true;
}
catch
{
return false;
}
}
void MEMCPY(byte[] Received, byte[] Buffer, int Len)
{
fixed (byte* pointer = Received, buffer = Buffer)
MSVCRT.MEMCPY(pointer, buffer, Len);
}
}
Socket Invoke Events:
Code:
public class SocketInvoke
{
public event Action<SocketClient> connection;
public event Action<SocketClient, byte[]> receive;
public event Action<SocketClient> disconnection;
/// <summary>
/// Invoking socket events.
/// </summary>
/// <param name="Client">The socket client.</param>
/// <param name="invoke">The socket event invoke type.</param>
/// <param name="Packet">The packet to invoke for receive. Can be null for connection & disconnection</param>
public void Invoke(SocketClient Client, Enums.SocketInvokeType invoke, byte[] Packet)
{
switch (invoke)
{
case ConquerServerProject.Enums.SocketInvokeType.Connection:
{
if (connection != null)
connection.Invoke(Client);
break;
}
case ConquerServerProject.Enums.SocketInvokeType.Receive:
{
if (receive != null)
receive.Invoke(Client, Packet);
break;
}
case ConquerServerProject.Enums.SocketInvokeType.Disconnection:
{
if (disconnection != null)
disconnection.Invoke(Client);
break;
}
}
}
}
Packet Client (Even you probably ain't gonna use it.)
Code:
public class PacketClient
{
public SocketClient Owner;
public PacketClient(SocketClient client)
{
Owner = client;
}
private void AddTQServer(byte[] Packet)
{
unsafe
{
fixed (byte* p = Packet)
{
string TQServer = "TQServer";
for (int i = 0; i < 8; i++)
*(p + i + Packet.Length - 8) = Convert.ToByte(TQServer[i]);
}
}
}
private Dictionary<uint, byte[]> PacketList = new Dictionary<uint, byte[]>();
public uint NextUID = 0;
private void AddPacket(byte[] Packet)
{
if (Packet == null)
return;
AddTQServer(Packet);
PacketList.Add(NextUID, Packet);
NextUID++;
if (PacketList.Count > 0)
{
Monitor.Enter(Owner);
try
{
byte[] _Packet = new byte[TotalLength()];
int Pos = 0;
lock (PacketList)
{
BlockCopy(_Packet, Pos);
}
PacketList = new Dictionary<uint, byte[]>();
}
catch { }
Monitor.Exit(Owner);
}
}
private int TotalLength()
{
int Ret = 0;
foreach (byte[] Packet in PacketList.Values)
{
if (Packet != null)
if (Packet.Length > 0)
Ret += Packet.Length;
}
return Ret;
}
private void BlockCopy(byte[] Packet, int Position)
{
foreach (byte[] P in PacketList.Values)
{
if (P.Length > 0)
{
#if !BUFFER_BLOCKCOPY
unsafe
{
fixed (byte* src = P, dest = Packet)
NativeImports.MSVCRT.MEMCPY(dest, src, Packet.Length);
}
#else
Buffer.BlockCopy(P, 0, Packet, Position, P.Length);
#endif
Position += P.Length;
}
}
Send(Packet, true);
}
/// <summary>
/// Send packets directly, do not call this, unless it's the authentication packet
/// </summary>
/// <param name="Packet"></param>
/// <param name="encrypt"></param>
public unsafe void Send(byte[] Packet, bool encrypt)
{
if (Owner.Owner != null)
{
if (encrypt)
{
try
{
(Owner.Owner as ConquerClient).Blowfish.Encrypt(Packet);
}
catch { }
}
}
try
{
byte[] Data = new byte[Packet.Length];
fixed (byte* src = Packet, dest = Data)
NativeImports.MSVCRT.MEMCPY(dest, src, Data.Length);
Owner.Cryption.Encrypt(Data);
Owner.Socket.Send(Data);
}
catch (Exception e)
{
Server.ErrorHandler.Handle(e);
}
}
/// <summary>
/// Game Client Packets
/// </summary>
/// <param name="Packet"></param>
public void Send(byte[] Packet)
{
try
{
AddPacket(Packet);
}
catch (Exception e)
{
Server.ErrorHandler.Handle(e);
}
NextUID = 0;
}
}
MSVCRT:
Code:
public unsafe class MSVCRT
{
[DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
public static extern unsafe void* MEMCPY(void* dest, void* src, int size);
}