|
You last visited: Today at 20:14
Advertisement
PacketBuilder
Discussion on PacketBuilder within the CO2 Private Server forum part of the Conquer Online 2 category.
11/30/2011, 21:23
|
#1
|
elite*gold: 0
Join Date: Feb 2011
Posts: 335
Received Thanks: 170
|
PacketBuilder
Alrighty, well I made this packetbuilder, I feel as if it can be improved though. Anyone have any ideas, any suggestions etc?
Code:
public unsafe class PacketBuilder
{
Byte* Buffer;
UInt16 Length;
public PacketBuilder(UInt16 Length)
{
this.Length = Length;
this.Buffer = (Byte*)Marshal.AllocHGlobal(Length).ToPointer();
for (UInt16 Zero = 0; Zero < Length; ++Zero)
Byte(0, Zero);
}
public void Byte(Byte[] Values, UInt32 Offset) { Marshal.Copy(Values, 0, (IntPtr)(Buffer + Offset), Values.Length); }
public void Byte(Byte Value, UInt32 Offset) { *((Byte*)(Buffer + Offset)) = Value; }
public void UInt16(UInt16 Value, UInt32 Offset) { *((UInt16*)(Buffer + Offset)) = Value; }
public void UInt32(UInt32 Value, UInt32 Offset) { *((UInt32*)(Buffer + Offset)) = Value; }
public void UInt64(UInt64 Value, UInt32 Offset) { *((UInt64*)(Buffer + Offset)) = Value; }
public void String(String[] Values, UInt32 Offset)
{
foreach (String Value in Values)
{
Byte[] StringBuffer = Encoding.ASCII.GetBytes(Value);
Marshal.Copy(StringBuffer, 0, (IntPtr)(Buffer + Offset), StringBuffer.Length);
Offset += (UInt32)StringBuffer.Length;
}
}
public void String(String Value, UInt32 Offset, Boolean WithLength)
{
Byte[] StringBuffer = Encoding.ASCII.GetBytes(Value);
if (WithLength) { Byte((Byte)StringBuffer.Length, Offset); ++Offset; }
Marshal.Copy(StringBuffer, 0, (IntPtr)(Buffer + Offset), StringBuffer.Length);
}
public void String(String[] Values, UInt32 Offset, Boolean WithLength)
{
foreach (String Value in Values)
{
Byte[] StringBuffer = Encoding.ASCII.GetBytes(Value);
if (WithLength) { Byte((Byte)StringBuffer.Length, Offset); ++Offset; }
Marshal.Copy(StringBuffer, 0, (IntPtr)(Buffer + Offset), StringBuffer.Length);
Offset += (UInt32)StringBuffer.Length;
}
}
public Byte[] ToByteArray()
{
Byte[] newBuffer = new Byte[this.Length];
Marshal.Copy((IntPtr)this.Buffer, newBuffer, 0, this.Length);
return newBuffer;
}
public static void Byte(Byte Value, UInt32 Offset, Byte[] Buffer)
{
fixed (Byte* buffer = Buffer)
*((Byte*)(buffer + Offset)) = Value;
}
public static void UInt16(UInt16 Value, UInt32 Offset, Byte[] Buffer)
{
fixed (Byte* buffer = Buffer)
*((UInt16*)(buffer + Offset)) = Value;
}
public static void UInt32(UInt32 Value, UInt32 Offset, Byte[] Buffer)
{
fixed (Byte* buffer = Buffer)
*((UInt32*)(buffer + Offset)) = Value;
}
public static void UInt64(UInt64 Value, UInt32 Offset, Byte[] Buffer)
{
fixed (Byte* buffer = Buffer)
*((UInt64*)(buffer + Offset)) = Value;
}
public static void String(String Value, UInt32 Offset, Byte[] Buffer, Boolean WithLength)
{
fixed (byte* buffer = Buffer)
{
if (WithLength)
{
Byte((Byte)Value.Length, Offset, Buffer);
++Offset;
}
Byte[] StringBuffer = Encoding.ASCII.GetBytes(Value);
Marshal.Copy(StringBuffer, 0, (IntPtr)(buffer + Offset), StringBuffer.Length);
}
}
}
|
|
|
12/01/2011, 00:16
|
#2
|
elite*gold: 0
Join Date: Jan 2008
Posts: 1,443
Received Thanks: 1,175
|
Quote:
Originally Posted by Arco.
Alrighty, well I made this packetbuilder, I feel as if it can be improved though. Anyone have any ideas, any suggestions etc?[...]
|
Seems really similar to the one I did for you. But, you need to free the memory and everything... Take a look at what I did. You'll be able to improve it. Oh, and as I said when I did the builder for you, you should use structures and pointers to them, it's faster.
If you no longer have mine.
Code:
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace COServer
{
public unsafe class PacketBuilder
{
public enum SeekMode
{
Set = 0,
Cur = 1,
End = 2,
};
private Encoding Encoding;
private Byte* pBuffer;
private Int32 Length;
private Int32 Position;
public PacketBuilder(Int32 Length)
{
this.Encoding = Encoding.GetEncoding("iso-8859-1");
this.pBuffer = (Byte*)Marshal.AllocHGlobal(Length).ToPointer();
this.Length = Length;
this.Position = 0;
//AllocHGlobal doesn't alloc zero-filled memory.
ZeroFill(Length);
this.Position = 0;
}
public PacketBuilder(Int32 Length, Encoding Encoding)
{
this.Encoding = Encoding;
this.pBuffer = (Byte*)Marshal.AllocHGlobal(Length).ToPointer();
this.Length = Length;
this.Position = 0;
//AllocHGlobal doesn't alloc zero-filled memory.
ZeroFill(Length);
this.Position = 0;
}
~PacketBuilder()
{
if (pBuffer != null)
Marshal.FreeHGlobal((IntPtr)pBuffer);
pBuffer = null;
}
public void Seek(Int32 Position, SeekMode Mode)
{
if (Mode == SeekMode.Set)
this.Position = Position;
else if (Mode == SeekMode.Cur)
this.Position += Position;
else if (Mode == SeekMode.End)
this.Position = Length - Position;
}
public Int32 Tell() { return Position; }
public void ZeroFill(Int32 Length)
{
for (Int32 i = 0; i < Length / 4; i++) //Should be faster for large block...
Write((Int32)0x00);
for (Int32 i = 0; i < Length % 4; i++)
Write((Byte)0x00);
}
public void Write(SByte Param) { *(pBuffer + Position) = (Byte)Param; Position += sizeof(SByte); }
public void Write(Byte Param) { *(pBuffer + Position) = Param; Position += sizeof(Byte); }
public void Write(Int16 Param) { *((Int16*)(pBuffer + Position)) = Param; Position += sizeof(Int16); }
public void Write(UInt16 Param) { *((UInt16*)(pBuffer + Position)) = Param; Position += sizeof(UInt16); }
public void Write(Int32 Param) { *((Int32*)(pBuffer + Position)) = Param; Position += sizeof(Int32); }
public void Write(UInt32 Param) { *((UInt32*)(pBuffer + Position)) = Param; Position += sizeof(UInt32); }
public void Write(Int64 Param) { *((Int64*)(pBuffer + Position)) = Param; Position += sizeof(Int64); }
public void Write(UInt64 Param) { *((UInt64*)(pBuffer + Position)) = Param; Position += sizeof(UInt64); }
public void Write(Byte[] Param) { Marshal.Copy(Param, 0, (IntPtr)(pBuffer + Position), Param.Length); Position += Param.Length * sizeof(Byte); }
public void Write(String Param)
{
Byte[] Buffer = Encoding.GetBytes(Param);
Marshal.Copy(Buffer, 0, (IntPtr)(pBuffer + Position), Buffer.Length);
Position += Buffer.Length;
}
public void Write(String[] Params)
{
foreach (String Param in Params)
{
Byte[] Buffer = Encoding.GetBytes(Param);
Marshal.Copy(Buffer, 0, (IntPtr)(pBuffer + Position), Buffer.Length);
Position += Buffer.Length;
}
}
public void Write(String Param, Boolean WithLength)
{
Byte[] Buffer = Encoding.GetBytes(Param);
if (WithLength)
Write((Byte)Buffer.Length);
Marshal.Copy(Buffer, 0, (IntPtr)(pBuffer + Position), Buffer.Length);
Position += Buffer.Length;
}
public void Write(String[] Params, Boolean WithLength)
{
foreach (String Param in Params)
{
Byte[] Buffer = Encoding.GetBytes(Param);
if (WithLength)
Write((Byte)Buffer.Length);
Marshal.Copy(Buffer, 0, (IntPtr)(pBuffer + Position), Buffer.Length);
Position += Buffer.Length;
}
}
public static implicit operator Byte[](PacketBuilder Packet)
{
Byte[] Buffer = new Byte[Packet.Length];
Marshal.Copy((IntPtr)Packet.pBuffer, Buffer, 0, Packet.Length);
return Buffer;
}
}
}
|
|
|
12/01/2011, 04:52
|
#3
|
elite*gold: 0
Join Date: Feb 2011
Posts: 335
Received Thanks: 170
|
Quote:
Originally Posted by CptSky
Seems really similar to the one I did for you. But, you need to free the memory and everything... Take a look at what I did. You'll be able to improve it. Oh, and as I said when I did the builder for you, you should use structures and pointers to them, it's faster.
If you no longer have mine.
Code:
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace COServer
{
public unsafe class PacketBuilder
{
public enum SeekMode
{
Set = 0,
Cur = 1,
End = 2,
};
private Encoding Encoding;
private Byte* pBuffer;
private Int32 Length;
private Int32 Position;
public PacketBuilder(Int32 Length)
{
this.Encoding = Encoding.GetEncoding("iso-8859-1");
this.pBuffer = (Byte*)Marshal.AllocHGlobal(Length).ToPointer();
this.Length = Length;
this.Position = 0;
//AllocHGlobal doesn't alloc zero-filled memory.
ZeroFill(Length);
this.Position = 0;
}
public PacketBuilder(Int32 Length, Encoding Encoding)
{
this.Encoding = Encoding;
this.pBuffer = (Byte*)Marshal.AllocHGlobal(Length).ToPointer();
this.Length = Length;
this.Position = 0;
//AllocHGlobal doesn't alloc zero-filled memory.
ZeroFill(Length);
this.Position = 0;
}
~PacketBuilder()
{
if (pBuffer != null)
Marshal.FreeHGlobal((IntPtr)pBuffer);
pBuffer = null;
}
public void Seek(Int32 Position, SeekMode Mode)
{
if (Mode == SeekMode.Set)
this.Position = Position;
else if (Mode == SeekMode.Cur)
this.Position += Position;
else if (Mode == SeekMode.End)
this.Position = Length - Position;
}
public Int32 Tell() { return Position; }
public void ZeroFill(Int32 Length)
{
for (Int32 i = 0; i < Length / 4; i++) //Should be faster for large block...
Write((Int32)0x00);
for (Int32 i = 0; i < Length % 4; i++)
Write((Byte)0x00);
}
public void Write(SByte Param) { *(pBuffer + Position) = (Byte)Param; Position += sizeof(SByte); }
public void Write(Byte Param) { *(pBuffer + Position) = Param; Position += sizeof(Byte); }
public void Write(Int16 Param) { *((Int16*)(pBuffer + Position)) = Param; Position += sizeof(Int16); }
public void Write(UInt16 Param) { *((UInt16*)(pBuffer + Position)) = Param; Position += sizeof(UInt16); }
public void Write(Int32 Param) { *((Int32*)(pBuffer + Position)) = Param; Position += sizeof(Int32); }
public void Write(UInt32 Param) { *((UInt32*)(pBuffer + Position)) = Param; Position += sizeof(UInt32); }
public void Write(Int64 Param) { *((Int64*)(pBuffer + Position)) = Param; Position += sizeof(Int64); }
public void Write(UInt64 Param) { *((UInt64*)(pBuffer + Position)) = Param; Position += sizeof(UInt64); }
public void Write(Byte[] Param) { Marshal.Copy(Param, 0, (IntPtr)(pBuffer + Position), Param.Length); Position += Param.Length * sizeof(Byte); }
public void Write(String Param)
{
Byte[] Buffer = Encoding.GetBytes(Param);
Marshal.Copy(Buffer, 0, (IntPtr)(pBuffer + Position), Buffer.Length);
Position += Buffer.Length;
}
public void Write(String[] Params)
{
foreach (String Param in Params)
{
Byte[] Buffer = Encoding.GetBytes(Param);
Marshal.Copy(Buffer, 0, (IntPtr)(pBuffer + Position), Buffer.Length);
Position += Buffer.Length;
}
}
public void Write(String Param, Boolean WithLength)
{
Byte[] Buffer = Encoding.GetBytes(Param);
if (WithLength)
Write((Byte)Buffer.Length);
Marshal.Copy(Buffer, 0, (IntPtr)(pBuffer + Position), Buffer.Length);
Position += Buffer.Length;
}
public void Write(String[] Params, Boolean WithLength)
{
foreach (String Param in Params)
{
Byte[] Buffer = Encoding.GetBytes(Param);
if (WithLength)
Write((Byte)Buffer.Length);
Marshal.Copy(Buffer, 0, (IntPtr)(pBuffer + Position), Buffer.Length);
Position += Buffer.Length;
}
}
public static implicit operator Byte[](PacketBuilder Packet)
{
Byte[] Buffer = new Byte[Packet.Length];
Marshal.Copy((IntPtr)Packet.pBuffer, Buffer, 0, Packet.Length);
return Buffer;
}
}
}
|
Yeah, the one you made, I took that and read it over, learned about pointers, and used it as a reference to make a builder. Simplified it a good bit, also explicitly declare offsets, return a ByteArray. Thanks to your builder, I learned a good bit about pointers <3
|
|
|
12/01/2011, 06:27
|
#4
|
elite*gold: 0
Join Date: May 2005
Posts: 1,892
Received Thanks: 920
|
Even better - pin the byte pointer so it's not swiped by the GC, and assign the internal pointer in the "packet" base class to the pointer to the byte array in a constructor *for packets to process* with the finalizer always freeing the unmanaged memory. Write a bunch of functions in the packet class to split up the fields by pointer arithmetic, derive all packets off of the packet class, and in these derived classes, use accessors to use the base class read and write functions. Tada, you're using just a tiny bit more memory and have a very slight performance degrade for 1028739x neater and more flexible packet handling than pointers to structures.
I've done all this except pinning the byte pointer and assigning it for processing packets (right now, we're copying the data over with memcpy... but hey, I'm never satisfied so what the hell), but there's probably something stupidly wrong with doing this... Now I'm going to go implement that. I'll let you know if what I said works or not. If someone knows it does/doesn't work, please tell me before I start wasting time. ;d
|
|
|
12/01/2011, 15:05
|
#5
|
elite*gold: 0
Join Date: Oct 2009
Posts: 63
Received Thanks: 10
|
i just realised that my packetbuilder is ****
|
|
|
12/01/2011, 20:46
|
#6
|
elite*gold: 12
Join Date: Jul 2011
Posts: 8,282
Received Thanks: 4,191
|
I don't use a packet builder. I make them using structs and send them to the client in one line of code. I never have to copy it... or process it... or waste processor time doing comparisons in the wrapper.
|
|
|
12/01/2011, 20:52
|
#7
|
elite*gold: 0
Join Date: May 2005
Posts: 1,892
Received Thanks: 920
|
Quote:
Originally Posted by Fаng
I don't use a packet builder. I make them using structs and send them to the client in one line of code. I never have to copy it... or process it... or waste processor time doing comparisons in the wrapper.
|
Doing it that way is ugly, time consuming, and not very object oriented.
|
|
|
12/01/2011, 21:03
|
#8
|
elite*gold: 12
Join Date: Jul 2011
Posts: 8,282
Received Thanks: 4,191
|
Quote:
Originally Posted by Lateralus
Doing it that way is ugly, time consuming, and not very object oriented.
|
Lol, if you say so o.o
I personally think it's much more organized than anything else I've seen. In addition to that, it's much faster than traditional packet building. I've tested it. =p
|
|
|
12/01/2011, 21:23
|
#9
|
elite*gold: 0
Join Date: Feb 2011
Posts: 335
Received Thanks: 170
|
Quote:
Originally Posted by Fаng
Lol, if you say so o.o
I personally think it's much more organized than anything else I've seen. In addition to that, it's much faster than traditional packet building. I've tested it. =p
|
Cause you've used every single method of packetbuilding known to man right?
Forgot, Fang is pro coder, my bad.
|
|
|
12/01/2011, 21:46
|
#10
|
elite*gold: 12
Join Date: Jul 2011
Posts: 8,282
Received Thanks: 4,191
|
Quote:
Originally Posted by Arco.
Cause you've used every single method of packetbuilding known to man right?
Forgot, Fang is pro coder, my bad.
|
Yes Arco. I actually have used every possible *good* and base way to code a packet in C#. It's called experience.
|
|
|
12/01/2011, 22:20
|
#11
|
elite*gold: 0
Join Date: May 2005
Posts: 1,892
Received Thanks: 920
|
Quote:
Originally Posted by Fаng
Lol, if you say so o.o
I personally think it's much more organized than anything else I've seen. In addition to that, it's much faster than traditional packet building. I've tested it. =p
|
How is your method "much faster" than mine? Using pointers to structures has exactly the same function as my packet class, except mine is much more flexible and object oriented. I'm pretty sure small accessors are inlined in my case, so what I have is unsafe code only in the packet class and beautiful code in the derived classes and everywhere that uses them that has the same performance as, if not faster than, your method, is much easier to work with, and follows proper OOP guidelines - not an opinion.
|
|
|
12/01/2011, 22:40
|
#12
|
elite*gold: 12
Join Date: Jul 2011
Posts: 8,282
Received Thanks: 4,191
|
Quote:
Originally Posted by Lateralus
How is your method "much faster" than mine? Using pointers to structures has exactly the same function as my packet class, except mine is much more flexible and object oriented. I'm pretty sure small accessors are inlined in my case, so what I have is unsafe code only in the packet class and beautiful code in the derived classes and everywhere that uses them that has the same performance as, if not faster than, your method, is much easier to work with, and follows proper OOP guidelines - not an opinion.
|
I was comparing it to traditional packet building. You don't have any stupid comparisons like Impulse's wrapper does. It should be fine. And as far as a difference between structs and pointer wrappers like yours... there is no difference (performance wise). I honestly like structs better. It's just a preference of mine.
Edit: Jack says there probably is a difference between structs and wrappers like yours - but it's so small that it wouldn't make a big difference.
|
|
|
12/01/2011, 23:02
|
#13
|
elite*gold: 0
Join Date: May 2005
Posts: 1,892
Received Thanks: 920
|
Quote:
Originally Posted by Fаng
Edit: Jack says there probably is a difference between structs and wrappers like yours - but it's so small that it wouldn't make a big difference.
|
If the compiler inlines small functions and accessors like mine, then there isn't a difference. As of right now, because I copy packets with memcpy into the internal pointer, yeah, there's a difference.
|
|
|
12/03/2011, 23:30
|
#14
|
elite*gold: 0
Join Date: Oct 2009
Posts: 31
Received Thanks: 1
|
I know this is stupid question but what exactly is a packetBuilder?
|
|
|
12/03/2011, 23:43
|
#15
|
elite*gold: 0
Join Date: Jul 2006
Posts: 2,216
Received Thanks: 794
|
PHP Code:
public static byte[] Serialize(object Data) { int size = Marshal.SizeOf(Data); byte[] bdata = new byte[size]; GCHandle handle = GCHandle.Alloc(bdata, GCHandleType.Pinned); Marshal.StructureToPtr(Data, handle.AddrOfPinnedObject(), false); handle.Free(); return bdata; }
|
|
|
Similar Threads
|
Packetbuilder
10/21/2011 - CO2 Programming - 18 Replies
I have a simple packetbuilder right now, but is there any way that this can be optimized for efficiency? class PacketBuilder
{
private byte buffer;
public PacketBuilder(byte Buffer)
{
buffer = Buffer;
}
public void ZeroFill(byte Buffer, ushort Offset, ushort Count)
{
|
Packetbuilder
10/13/2011 - General Coding - 0 Replies
I have a simple packetbuilder right now, but is there any way that this can be optimized for efficiency? class PacketBuilder
{
private byte buffer;
public PacketBuilder(byte Buffer)
{
buffer = Buffer;
}
public void ZeroFill(byte Buffer, ushort Offset, ushort Count)
{
|
All times are GMT +1. The time now is 20:15.
|
|