Page 6 of 7 FirstFirst ... 4567 LastLast
Results 51 to 60 of 66

Thread: Game Network Engine

  1. #51

    Game Network Engine

    i don't think that it will work with udp :? or will?
    From brazil (:

    Pascal pownz!

  2. #52

    Game Network Engine

    Quote Originally Posted by arthurprs
    i don't think that it will work with udp :? or will?
    Why not?
    You can read and write data via UDP the same as TCP, it just isn't guarenteed to arrive at its destination, or in the correct order.

    the read/write bit should still work if you make a TPacketWriter/Reader descendant to write/read data using UDP, let's say via Synapse for example.

    cheers,
    Paul

  3. #53

    Game Network Engine

    Hi arthurprs,
    I just wrote a quick project containing the stream reader/writer I already presented, but now also has synapse UDP reader/writer classes too

    It has a test for both types of reader/writer combos, and both tests work for me (including the UDP)...

    Code:
    program reader_writer_test;
    {$APPTYPE CONSOLE}
    uses
      SysUtils,
      packet_types,
      packet_classes,
      Classes,
      blcksock;
    
    Type
    {..............................................................................}
        TPacketReader_Stream = Class(TPacketReader)
        Private
            FStream : TStream;
        Protected
            Function ReadData(Const AData : Pointer; Const ADataSize : LongInt) : Boolean;  Override;
        Public
            Constructor Create(Const AStream : TStream);
        End;
    {..............................................................................}
    
    {..............................................................................}
        TPacketWriter_Stream = Class(TPacketWriter)
        Private
            FStream : TStream;
        Protected
            Function WriteData(Const AData : Pointer; Const ADataSize : LongInt) : Boolean; Override;
        Public
            Constructor Create(Const AStream : TStream);
        End;
    {..............................................................................}
    
    {..............................................................................}
        TPacketReader_Synapse_UDP = Class(TPacketReader)
        Private
            FSocket : TUDPBlockSocket;
        Protected
            Function ReadData(Const AData : Pointer; Const ADataSize : LongInt) : Boolean;  Override;
        Public
            Constructor Create(Const ASocket : TUDPBlockSocket;
                               Const APort   : AnsiString);
        End;
    {..............................................................................}
    
    {..............................................................................}
        TPacketWriter_Synapse_UDP = Class(TPacketWriter)
        Private
            FSocket : TUDPBlockSocket;
            FIP     : AnsiString;
            FPort   : AnsiString;
        Protected
            Function WriteData(Const AData : Pointer; Const ADataSize : LongInt) : Boolean; Override;
        Public
            Constructor Create(Const ASocket    : TUDPBlockSocket;
                               Const AIP, APort : AnsiString);
        End;
    {..............................................................................}
    
    Constructor TPacketReader_Stream.Create(Const AStream : TStream);
    Begin
        Inherited Create;
        FStream := AStream;
    End;
    {..............................................................................}
    
    {..............................................................................}
    Function TPacketReader_Stream.ReadData(Const AData : Pointer; Const ADataSize : LongInt) : Boolean;
    Type
        PByte = ^Byte;
    Begin
        Result := FStream.Read(PByte(AData)^,ADataSize) = ADataSize;
    End;
    {..............................................................................}
    
    {..............................................................................}
    Constructor TPacketWriter_Stream.Create(Const AStream : TStream);
    Begin
        Inherited Create;
        FStream := AStream;
    End;
    {..............................................................................}
    
    {..............................................................................}
    Function TPacketWriter_Stream.WriteData(Const AData : Pointer; Const ADataSize : LongInt) : Boolean;
    Type
        PByte = ^Byte;
    Begin
        Result := FStream.Write(PByte(AData)^,ADataSize) = ADataSize;
    End;
    {..............................................................................}
    
    {..............................................................................}
    Constructor TPacketReader_Synapse_UDP.Create(Const ASocket : TUDPBlockSocket;
                                                 Const APort   : AnsiString);
    Begin
        Inherited Create;
        FSocket := ASocket;
        FSocket.Bind('0.0.0.0',APort);
    End;
    {..............................................................................}
    
    {..............................................................................}
    Function TPacketReader_Synapse_UDP.ReadData(Const AData : Pointer; Const ADataSize : LongInt) : Boolean;
    Type
        PByte = ^Byte;
    Begin
        FSocket.RecvBuffer(AData,ADataSize);
        Result := FSocket.LastError = 0;
        If Not Result Then WriteLn('TPacketReader_Synapse_UDP: ',FSocket.LastErrorDesc);
    End;
    {..............................................................................}
    
    {..............................................................................}
    Constructor TPacketWriter_Synapse_UDP.Create(Const ASocket    : TUDPBlockSocket;
                                                 Const AIP, APort : AnsiString);
    Begin
        Inherited Create;
        FSocket := ASocket;
        FIP     := AIP;
        FPort   := APort;
    End;
    {..............................................................................}
    
    {..............................................................................}
    Function TPacketWriter_Synapse_UDP.WriteData(Const AData : Pointer; Const ADataSize : LongInt) : Boolean;
    Begin
        FSocket.Connect(FIP,FPort);
        FSocket.SendBuffer(AData,ADataSize);
        Result := FSocket.LastError = 0;
        If Not Result Then WriteLn('TPacketWriter_Synapse_UDP: ',FSocket.LastErrorDesc);
    End;
    {..............................................................................}
    
    {..............................................................................}
    Procedure WritePackets(Const APacketWriter : TPacketWriter);
    Begin
        APacketWriter.WriteLoginPacket ('UserName','PassWord');
        APacketWriter.WriteChatPacket  ('Message#1');
        APacketWriter.WriteChatPacket  ('Message#2');
        APacketWriter.WriteChatPacket  ('Message#3');
        APacketWriter.WriteChatPacket  ('Message#4');
        APacketWriter.WriteChatPacket  ('Message#5');
        APacketWriter.WriteChatPacket  ('Message#6');
        APacketWriter.WriteLogoffPacket('UserName','PassWord');
    End;
    {..............................................................................}
    
    {..............................................................................}
    Procedure ProcessLoginPacket(Const APacket : PPacket_Login);
    Begin
        WriteLn('Login Packet:');
        WriteLn('  ',APacket^.UserName);
        WriteLn('  ',APacket^.PassWord);
    End;
    {..............................................................................}
    
    {..............................................................................}
    Procedure ProcessLogoffPacket(Const APacket : PPacket_Logoff);
    Begin
        WriteLn('Logoff Packet:');
        WriteLn('  ',APacket^.UserName);
        WriteLn('  ',APacket^.PassWord);
    End;
    {..............................................................................}
    
    {..............................................................................}
    Procedure ProcessChatPacket(Const APacket : PPacket_Chat);
    Begin
        WriteLn('Chat Packet: ');
        WriteLn('  ',APacket^.Msg);
    End;
    {..............................................................................}
    
    {..............................................................................}
    Procedure ReadPackets(Const APacketReader : TPacketReader);
    Var
        Packet   : Pointer;
        Finished : Boolean;
    Begin
        Finished := False;
        While Not Finished Do
        Begin
            If APacketReader.ReadPacket(Packet) Then
            Begin
                Case PPacket(Packet)^.PacketType Of
                    ePacketType_Login  : ProcessLoginPacket (Packet);
                    ePacketType_Logoff : ProcessLogoffPacket(Packet);
                    ePacketType_Chat   : ProcessChatPacket  (Packet);
                Else
                    {unknown packet so do error or something}
                End;
                If PPacket(Packet)^.PacketType = ePacketType_Logoff Then
                    Finished := True;
                APacketReader.FreePacket(Packet);
            End;
        End;
    End;
    {..............................................................................}
    
    {..............................................................................}
    Procedure RunTest_Stream;
    Var
        MemoryStream : TMemoryStream;
        PacketReader : TPacketReader;
        PacketWriter : TPacketWriter;
    Begin
        MemoryStream := TMemoryStream.Create;
    
        PacketWriter := TPacketWriter_Stream.Create(MemoryStream);
        PacketReader := TPacketReader_Stream.Create(MemoryStream);
    
        WritePackets(PacketWriter);
        MemoryStream.Position := 0;
        ReadPackets(PacketReader);
        MemoryStream.Free;
        PacketReader.Free;
        PacketWriter.Free;
    End;
    {..............................................................................}
    
    {..............................................................................}
    Procedure RunTest_UDP;
    Var
        ClientSocket : TUDPBlockSocket;
        ServerSocket : TUDPBlockSocket;
        PacketReader : TPacketReader;
        PacketWriter : TPacketWriter;
    Begin
        ClientSocket := TUDPBlockSocket.Create;
        ServerSocket := TUDPBlockSocket.Create;
    
        PacketWriter := TPacketWriter_Synapse_UDP.Create(ClientSocket,'LocalHost','12000');
        PacketReader := TPacketReader_Synapse_UDP.Create(ServerSocket,'12000');
    
        WritePackets(PacketWriter);
        ReadPackets(PacketReader);
        ClientSocket.Free;
        ServerSocket.Free;
        PacketReader.Free;
        PacketWriter.Free;
    End;
    {..............................................................................}
    
    {..............................................................................}
    Begin
        WriteLn('*********************');
        WriteLn('**** stream test ****');
        WriteLn('*********************');
        RunTest_Stream;
        WriteLn('******************');
        WriteLn('**** UDP test ****');
        WriteLn('******************');
        RunTest_UDP;
        WriteLn('Press Enter to continue!');
        ReadLn;
    End.
    cheers,
    Paul

  4. #54

    Game Network Engine

    Quote Originally Posted by paul_nicholls
    Quote Originally Posted by arthurprs
    i don't think that it will work with udp :? or will?
    Why not?
    You can read and write data via UDP the same as TCP, it just isn't guarenteed to arrive at its destination, or in the correct order.

    the read/write bit should still work if you make a TPacketWriter/Reader descendant to write/read data using UDP, let's say via Synapse for example.

    cheers,
    Paul
    since the packets have diferent sizes
    how do you will receive then (you don't know the type of package, any package can arrive anytime in anyorder) :? ?
    From brazil (:

    Pascal pownz!

  5. #55

    Game Network Engine

    Quote Originally Posted by arthurprs
    Quote Originally Posted by paul_nicholls
    Quote Originally Posted by arthurprs
    i don't think that it will work with udp :? or will?
    Why not?
    You can read and write data via UDP the same as TCP, it just isn't guarenteed to arrive at its destination, or in the correct order.

    the read/write bit should still work if you make a TPacketWriter/Reader descendant to write/read data using UDP, let's say via Synapse for example.

    cheers,
    Paul
    since the packets have diferent sizes
    how do you will receive then (you don't know the type of package, any package can arrive anytime in anyorder) :? ?
    When I do get packets (including the packet type), I get the whole packet, it is just the order of the received packets that could be out of order (Not LAN, but over internet or possibly WAN too)...

    If I want to worry about that issue, I would put in a time-stamp on the packets and disregard out of order packets (if not super important)

    Also it doesn't matter that the packet sizes are different, the send/receive code takes care of that for me regardless of the reader/writer class being used.

    I hope this makes sense,
    cheers,
    Paul

  6. #56

    Game Network Engine

    Quote Originally Posted by paul_nicholls
    Quote Originally Posted by arthurprs
    Quote Originally Posted by paul_nicholls
    Quote Originally Posted by arthurprs
    i don't think that it will work with udp :? or will?
    Why not?
    You can read and write data via UDP the same as TCP, it just isn't guarenteed to arrive at its destination, or in the correct order.

    the read/write bit should still work if you make a TPacketWriter/Reader descendant to write/read data using UDP, let's say via Synapse for example.

    cheers,
    Paul
    since the packets have diferent sizes
    how do you will receive then (you don't know the type of package, any package can arrive anytime in anyorder) :? ?
    When I do get packets (including the packet type), I get the whole packet, it is just the order of the received packets that could be out of order (Not LAN, but over internet or possibly WAN too)...

    If I want to worry about that issue, I would put in a time-stamp on the packets and disregard out of order packets (if not super important)

    Also it doesn't matter that the packet sizes are different, the send/receive code takes care of that for me regardless of the reader/writer class being used.

    I hope this makes sense,
    cheers,
    Paul
    uhm, you don't need to specify the amount of data you want to receive?
    From brazil (:

    Pascal pownz!

  7. #57

    Game Network Engine

    Quote Originally Posted by arthurprs
    uhm, you don't need to specify the amount of data you want to receive?
    If you look at the code I posted, then you can see that I do.

    Code:
    Function  TPacketWriter.WritePacket(Const APacket : PPacket) : Boolean;
    Var
        DataSize : LongInt;
    Begin
        Result := False;
        Case APacket^.PacketType Of
            ePacketType_Login  : DataSize := SizeOf(TPacket_Login);
            ePacketType_Logoff : DataSize := SizeOf(TPacket_Logoff);
            ePacketType_Chat   : DataSize := SizeOf(TPacket_Chat);
        Else
            Exit;
        End;
        If Not WriteData(@DataSize,SizeOf(DataSize)) Then Exit;
        If Not WriteData(APacket,DataSize)           Then Exit;
        Result := True;
    End;
    You can see that I send the size of the packet first, then the packet itself...

    On the receiving end I read the datasize first, then use that datasize to read the packet itself.

    Code:
    Function TPacketReader.ReadPacket(Var APacket : Pointer) : Boolean;
    Var
        DataSize : LongInt;
        Packet   : Pointer;
    Begin
        Result := False;
        If Not ReadData(@DataSize,SizeOf(DataSize)) Then Exit;
        GetMem(Packet,DataSize);
        If Not ReadData(Packet,DataSize) Then
        Begin
            FreeMem(Packet);
            Exit;
        End;
        APacket := Packet;
        Result  := True;
    End;
    As you can hopefully see, this does not depend on the type of Packet reader/writer descendant you write :-)

    I hope this helps :-)
    cheers,
    Paul

  8. #58

    Game Network Engine

    great =D

    now i understand
    From brazil (:

    Pascal pownz!

  9. #59

    Game Network Engine

    I'm glad I could help
    BTW, I have made a small change to the code to make it a bit nicer.

    In the packet_classes.pas file I have added a cPacketSizeArray Constant.

    Code:
    Implementation
    
    Const
    {..............................................................................}
        cPacketSizeArray: Array[TPacketType] Of LongInt =
        (
            SizeOf(TPacket_Login),
            SizeOf(TPacket_Logoff),
            SizeOf(TPacket_Chat)
        );
    {..............................................................................}
    
    {..............................................................................}
    and changed the TPacketWriter.WritePacket() method to use this instead of the case statement:

    Code:
    Function  TPacketWriter.WritePacket(Const APacket : PPacket) : Boolean;
    Var
        DataSize : LongInt;
    Begin
        Result   := False;
        DataSize := cPacketSizeArray[APacket^.PacketType];
        If Not WriteData(@DataSize,SizeOf(DataSize)) Then Exit;
        If Not WriteData(APacket,DataSize)           Then Exit;
        Result := True;
    End;
    The code is a bit better now I think :-)

    cheers,
    Paul

  10. #60

    Game Network Engine

    Thanks to some ideas from Pyrogine, I have now re-written my packet stuff so the packets are now Classes instead of records

    The code is a bit more complex now, but I think it is more flexible in the long run.

    You still create 'concrete' packet reader and writer classes to read/write the packets to wherever you want (Stream, UDP, TCP, etc).

    You create new 'concrete' packet types by descending from TPacket_Base, overriding the WriteToStream and ReadFromStream methods so you control which fields in the class get written and read, and add a new cPacketID_ constant for that packet type.

    You also override the Create method to set the PacketID to the correct type.

    The base packet class even has its own Assign method that uses the 'concrete' packet classes' own WriteToStream and ReadFromStream methods so you can assign one packet to another of the same type without adding any extra code

    You register the all the packet types you are going to use with the PacketReader instance you are using, and 'away you go'

    So, if anyone is interested, here is the new code http://fpc4gp2x.eonclash.com/downloa...riter_test.zip

    Enjoy

    cheers,
    Paul

Page 6 of 7 FirstFirst ... 4567 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •