Example Source of Reliable TCP Packets with Headers and Data, OOP.

Greetings,

I need some good example code that deals with TCP packets where there is a known header with data length as part of the header (including header) and data.

Would like it to be asyncronous if possible.  I need to be able to send data from a memo line and stuff.  Perhaps an OnPacket event or something that gets called where there is a full packet available.

Anyway, this is what I am working with.

(BYTE)      StartPacket - always 0xFF
(BYTE)      Packet ID
(WORD)    Packet length, including this header
(VOID)      Packet Data

I did get something sort of working with using Indy Client, but it gets stuck in between packets and I can't send anything.  Also I find it crashes with errors when you close the program while it is waiting for data to read and stuff.

I would love for it to be OOP (object oriented programming).  Meaning making a object that is based off of TObject and has an event of OnPacket or something that is called when it gets a full packets with all the data and stuff and passes the data along to the event.

OnPacket(PacketID, Length, data)


Anyway, here is some source I got so far that I want to scratch and use some asycronious method...  I'd really not like to have to deal with threads is if I don't have to.

      while BNET.Connected do
      begin
        try
          BNET.ReadBuffer(StartPacket,1);
          BNET.ReadBuffer(PacketID,1);
          BNET.ReadBuffer(AByte,1);
          BNET.ReadBuffer(PacketLength,1);
          PacketLength := (PacketLength SHL 8) + AByte;
          BNET.ReadBuffer(PacketData,PacketLength-4);
        except
          on E: Exception do
            begin
              OutPutBox.Lines.Add('Error: '+E.Message);
              BNET.Disconnect
            end;
        end;
        Case StartPacket of
          $FF :
            Case PacketID of
              SID_CLANINVITE : OutPutBox.Lines.Add('  SID_CLANINVITE');
              //...
              SID_CLANMOTD : OutPutBox.Lines.Add('  SID_CLANMOTD');
          Else
            Begin
            End;
        End;
        If Terminated then BNET.Disconnect;
      end;

PS - I'd love to be able to give more than 500 points for this too, but it won't let me.  :)
werehamster-Asked:
Who is Participating?
 
JaccoConnect With a Mentor Commented:
Hi there,

(just nosing around in your questions) ;-)

This might be fast,

function ReverseWord(const aWord: Word): Word;
begin
  Result := Lo(aWord) shl 8 or Hi(aWord);
end;

To see how a word is built up from bytes:

procedure TForm1.Button1Click(Sender: TObject);
var
  lWord: Word;
  lSS: TStringStream;
begin
  lSS := TStringStream.Create('');
  try
    lWord := Ord('A') shl 8 + Ord('B'); // Hi = A Lo = B
    lSS.WriteBuffer(lWord, 2);
    Memo1.Lines.Add(lSS.DataString);
  finally
    lSS.Free;
  end;
end;

It shows "BA" so the low byte is stored first just like in you sample, so I think you don't need to reverse at all.

I think you can do it this:

  var
    PacketLength: Word;
  ...
  while BNET.Connected do
      begin
        try
          BNET.ReadBuffer(StartPacket,1);
          BNET.ReadBuffer(PacketID,1);
          BNET.ReadBuffer(PacketLength,2);
          BNET.ReadBuffer(PacketData,PacketLength-4);

Or of course the buffered reading I showed in my comment in your other question.

Did you have time to test the code?

Regards Jacco
0
 
werehamster-Author Commented:
Not exactly what I am looking for.  I did, however, figure out how to make a good reader thread that seems to work well.  I'll leave this up for the purpose of others looking into this topic to find an answer.

I do have a side question though, I have an indy client, when I disconnect while in the GUI, I get an error message.  When I run the executable seperately, it runs fine.  Any thoughts?
0
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
MolandoConnect With a Mentor Commented:
You are probably getting ConnectionClosedGracefully.
Do not worry about this, this is normal. Just get delphi to ignore these errors when in the GUI.
tools->debugger options->language exceptions->add->EldSilentException
(may have not spelt that correctly, check the indy docs.
0
 
werehamster-Author Commented:
Got another stupid, unrelated question.

I am reading a TCP Packet.  Parts are called a DWord in the description, but is not the same as a delphi DWord.

It is only 2 bytes long, but the bytes are reversed I think...

ie:/ 0100 = 0001,  0001 = $0100, etc.

I assume that is not how a word is stored normally when you Writebuffer(aword,sizeof(aword));

There a really quick way to reverse the bytes that I do not know?  Right now, I am reading 1 byte, then adding the 2nd byte with SHL 8.  re: Value = Byte1 + Byte2 SHL 8.  Is there a faster/quicker/better way than what I am doing?

I'll divide the points appropriately for those that can give good advice on this.  If I had a whole string of these, I was thinking that I could do...

Blah = (Blah and $0F0F0F0F) SHL 8 + ((Blah and $F0F0F0F0) SHR 8)

Any thoughts/advice?
0
 
werehamster-Author Commented:
Didn't have much time to test much of anything yet.  Got a couple days off to do it today and tommorow though.  I'll see if I can fit it into my busy schedule.  Rewriting a huge portion of my code, not just networking.  I'm a stickler for stability.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.