Solved

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

Posted on 2004-08-30
6
250 Views
Last Modified: 2013-11-23
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.  :)
0
Comment
Question by:werehamster-
6 Comments
 
LVL 12

Expert Comment

by:Ivanov_G
ID: 11939672
0
 

Author Comment

by:werehamster-
ID: 11940609
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
 
LVL 2

Assisted Solution

by:Molando
Molando earned 175 total points
ID: 11940850
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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:werehamster-
ID: 11949200
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
 
LVL 10

Accepted Solution

by:
Jacco earned 325 total points
ID: 12041376
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
 

Author Comment

by:werehamster-
ID: 12044079
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

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
This is used to tweak the memory usage for your computer, it is used for servers more so than workstations but just be careful editing registry settings as it may cause irreversible results. I hold no responsibility for anything you do to the regist…
Learn how to create flexible layouts using relative units in CSS.  New relative units added in CSS3 include vw(viewports width), vh(viewports height), vmin(minimum of viewports height and width), and vmax (maximum of viewports height and width).

863 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now