menu
  Home  ==>  papers  ==>  db  ==>  sniffing_interbase_traffic   

Sniffing Interbase Traffic - Felix John COLIBRI.


1 - Introduction

Interbase already comes complete with several logging and monitoring tools. However those tools mainly work at the application level. For instance, the Interbase Express monitor simply displays what Jeff Overcash decided to present: at chosen points, before sending orders to the Interbase Client, the Interbase Express unit writes some text to the Ibx monitor. The IbxSqlMonitor is a great tool, but its main purpose is to give the Delphi programmer some feedback of the progress of his requests. If you wish to analyze the traffic in terms of bytes, a lower level monitoring tool like a network sniffer comes handy.

In this paper we are going to use the sniffer that we built in the TCP IP Sniffer paper and will compare, as an example, the traffic generated by using different Interbase components: Ibx, the Bde and direct API calls to the Interbase Client DLL.

Before starting, I want to stress that we simply want to test the performance of the different access components. Our goal is NOT to snoop the meaning of the data transferred (the salary and stock options of your boss). The user can always encrypt his data, and the packet content will be opaque. We are interested by the volume of information, and will look at the content only to see what Interbase overhead is included in the packets (schema information and the like). This Interbase content analysis is precisely the benefit of sniffing over simple timing: we can identify the cause of the problem, and possibly find a remedy.




2 - Creating the Interbase Application

2.1 - The test bed

To have a flexible test bed, we are going to build the database and the table which we want to analyze with a small Interbase Express program. If you are familiar with Ibx programming, you can skip this part. You can also use an existing Database instead of creating a dedicated one like we are doing here.

2.2 - Create the Database

We create the Database using the usual CreateDatabase instruction:
   create a new application and call il "p_create_sniffed_database"
   place a tIbDatabase component on your tForm
   drop a tButton, create its OnClick event, and create the database:

const k_database_disk_path'\\notebook\c\programs\fr\colibri_utilities\programs\interbase_sniffer\_data\';
      k_database_path'notebook:c:/programs/fr/colibri_utilities/programs/interbase_sniffer/_data/';
      k_database_name'ib_sniffer.GDB';

procedure TForm1.create_database_Click(SenderTObject);
  begin
    IbDatabase1.Close;

    f_create_path(g_database_disk_path);

    with IbDatabase1Params do
    begin
      Connected:= False;

      DatabaseName:= g_database_pathk_database_name;
      SqlDialect:= 3;
      Clear;

      Add('USER 'QuotedStr('SYSDBA'));
      Add('PASSWORD 'QuotedStr('masterkey'));
      Add('PAGE_SIZE 4096');

      CreateDatabase;
    end// IbDatabase1
  end// create_database_Click

   compile, run and click Button1
Please note that:
  • we have placed the base on a remote PC. Sniffing TCP IP does NOT work on local bases: the TCP IP stack is not used, and therefore sniffing does not work
  • to make sure that the path exists, we called f_create_path which calls ForceDirectories to build the desired path. The parameter is a Windows parameter
  • to create the Database, we used an Interbase connection string, which is not exactly the same as the Windows path
  • we chose Interbase Dialect 3, which offers DateTime and huge integers, but you may prefer to stick with Dialect 1. The page size is the standard one that we use all the time, but changing this value might obviously have some influence on the benchmarking
  • we placed all the strings in constants, as you can see by looking at the .ZIP, the constants are all in an include file which is called by all our projects, to avoid any mis spelling
  • we also added in the .ZIP a DROP DATABASE button to be able to restart the whole trial again.


2.3 - Create the Table

The table is created with the classic CREATE TABLE request:

 CREATE TABLE my_table
     (field_1 type_1, field_2 type_2, ..., field_n type_n)

In our case:
   drop another tIbDatabase, a tIbTransaction and link those together.
Double click on tIbDatabase to open the connection editor, and fill in the DatabaseName, User, Password, remove the Login checkbox and hit "Test" to check the connection:

   drop an tIbSql component, link it to IbDatabase1
   place a tButton, create its OnClick event, and create a "reasonable" table:

const k_sql_create_table=
            'CREATE TABLE 'k_table_name
          + '  ('
          + '     s_id INTEGER, '
          + '     s_company CHAR(40), '
          + '     s_address CHAR(50), '
          + '     s_contact CHAR(20), '
          + '     s_amount_due DOUBLE PRECISION'
          + '  ) ';

procedure execute_sql(p_sql_queryString);
    // -- this procedure will sent any "write" sql request to the remote database
  begin
    with Form1write_ib_sql do
    begin
      Close;

      with Sql do
      begin
        Clear;
        Add(p_sql_query);
      end// with Sql

      Try
        write_IbDatabase.Open;
        write_IbDatabase.DefaultTransaction.Active:= True;

        if write_IbDatabase.DefaultTransaction.InTransaction
          then write_IbDatabase.DefaultTransaction.Commit;

        write_IbDatabase.DefaultTransaction.StartTransaction;

        ExecQuery;

        write_IbDatabase.DefaultTransaction.Commit;

        display('  ok');
      except
        on eException do
          begin
            write_IbDatabase.DefaultTransaction.RollBack;
            display('  *** exec 'e.Message);
          end;
      end;
    end// with IbSql1
  end// execute_sql

procedure TForm1.create_table_Click(SenderTObject);
  begin
    write_IbDatabase.Close;
    write_IbDatabase.DatabaseName:= g_database_pathk_database_name;

    execute_sql(k_sql_create_table);
  end// create_Click

   compile, run and click Button1


Note that:

  • we have placed the creation request in a litteral constant, as explained above
  • the creation itself has been split in two:
    • a general procedure execute_sql, which sends any "write" request to the Interbase Server (CREATE INDEX, DROP CONSTRAINT, ALTER COLUMN : anything but SELECT  )
    • the procedure create_table_Click to send the CREATE TABLE request
    The generic write request procedure will be used later for populating the table
  • in the .ZIP we added a "drop_table_" button to allow several runs.


2.4 - Populate the Table

The addition of rows in a table is performed with the INSERT INTO request:

 INSERT INTO my_table
     (field_1, field_2, ... , field_n)
     VALUES (value_1, value_2, ... , value_n)

To have a reasonable amount of data available, we automated the generation using random numbers:

  • we extracted the client names and adresses from the CUSTOMER table from DBDEMO. Those were saved in a .TXT file
  • we load this file in a tStringList
  • for each row in our table, we generate a random number from 0 to tStringList.Count- 1, and this will become our new customer.
The INSERT INTO request itself is built by simply inserting the radom generated values, and the whole process driven by a classic FOR loop.



Let's first extract the values from the DBDEMO table (or any table of your choice):

  • drop another tButton on the tForm, call it "extract_bde" and type the extraction text:

    const k_company_list_name'company.txt';
          k_address_list_name'address.txt';
          k_contact_list_name'contact.txt';

    procedure TForm1.extract_bde_Click(SenderTObject);
      var l_c_company_name_listl_c_address_listl_c_contact_listtStringList;
      begin
        l_c_company_name_list:= tStringList.Create;
        l_c_address_list:= tStringList.Create;
        l_c_contact_list:= tStringList.Create;

        With extract_table do
        begin
          DataSource1.DataSet:= extract_table;
          Open;
          First;
          While Not Eof do
          begin
            l_c_company_name_list.Add(FieldByName('Company').AsString);
            l_c_address_list.Add(FieldByName('Addr1').AsString);
            l_c_contact_list.Add(FieldByName('Contact').AsString);

            Next;
          end// While Not Eof
        end// With IbQuery1

        l_c_company_name_list.SaveToFile(g_database_disk_pathk_company_list_name);
        l_c_company_name_list.Free;

        l_c_address_list.SaveToFile(g_database_disk_pathk_address_list_name);
        l_c_address_list.Free;

        l_c_contact_list.SaveToFile(g_database_disk_pathk_contact_list_name);
        l_c_contact_list.Free;
      end// extract_bde_Click




And here is the insertion part:
   drop another tButton on the tForm, call it "insert", and type the insertion text:

function f_double_to_sql_string(p_doubleDouble): String;
  var l_save_decimal_separatorChar;
  begin
    l_save_decimal_separator:= DecimalSeparator;
    DecimalSeparator:= '.';
    Result:= FloatToStr(p_double);
    DecimalSeparator:= l_save_decimal_separator;
    Result:= f_replace_character(Result',''.');
  end// l_save_decimal_separator

procedure TForm1.insert_Click(SenderTObject);

  procedure insert_generic(p_idIntegerp_company_namep_addressp_contactString;
      p_amount_dueDouble);
    var l_valuesString;
        l_sql_requestString;
    begin
      l_values:=
            IntToStr(p_id)+ ', '
          + QuotedStr(p_company_name)+ ', '
          + QuotedStr(p_address)+ ', '
          + QuotedStr(p_contact)+ ', '
          + f_double_to_sql_string(p_amount_due);

      l_sql_request:= k_sql_insert_partial
        + ' ('l_values')';
      execute_sql(l_sql_request);
    end// insert_generic

  var l_c_company_name_listl_c_address_listl_c_contact_listtStringList;
      l_line_indexInteger;

      l_sample_countInteger;
      l_company_name_randoml_address_randoml_contact_randomString;
      l_amount_due_randomDouble;

  begin // insert_Click
    write_IbDatabase.Close;
    write_IbDatabase.DatabaseName:= g_database_pathk_database_name;

    l_c_company_name_list:= tStringList.Create;
    l_c_company_name_list.LoadFromFile(g_database_disk_pathk_company_list_name);
    l_sample_count:= l_c_company_name_list.Count;

    l_c_address_list:= tStringList.Create;
    l_c_address_list.LoadFromFile(g_database_disk_pathk_address_list_name);

    l_c_contact_list:= tStringList.Create;
    l_c_contact_list.LoadFromFile(g_database_disk_pathk_contact_list_name);

    for l_line_index:= 0 to StrToInt(insert_count_edit_.Text)- 1 do
    begin
      l_company_name_random:= l_c_company_name_list[Random(l_sample_count)];
      l_address_random:= l_c_address_list[Random(l_sample_count)];
      l_contact_random:= l_c_contact_list[Random(l_sample_count)];
      l_amount_due_random:= 23000+ Random(150000)/ 10;

      insert_generic(1000+ l_line_indexl_company_name_randoml_address_random,
          l_contact_randoml_amount_due_random);
    end// for l_line_index
  end// insert_Click

Notice that we used QuotedStr to avoid any single vs double quote, which are not the same in Interbase Dialect 1 and Dialect 3

   compile, execute and click
   here is our application in full swing:




Our base is ready, and we can easily change the content of our table (add columns, different types, increase the row count...). You can also add some bells and whistles, like:
  • an edit to allow the user to set the line count
  • a button to empty the table



3 - Sniffing Interbase Express

We are now ready for the main action. We will launch a SELECT query, and measure the traffic of this instruction. So we will:

3.1 - The Sniffing part

The sniffing part is done by importing the c_packet_sniffer into our project. A you may remember, this CLASS can start the sniffing, and collect statistics about the packet count and sizes.

The use of the c_packet_sniffer would still require the tedious link of all collected data to visual controls of our application. We already did this display in the p_packet_sniffer application, but we do not wish to build the SELECT in that main form. Regrettably Delphi offers no way to isolate a group of controls from a Form. We can try to do some "Save As" gimmickery, or use copy and paste, but that's about it. Of course we can create a brand new component, but this would be an overkill. So we will use a CLASS which will create the visual controls "by hand", like in olden OWL time, and use this CLASS, and use this c_display_packet CLASS in our project.

Here is a snapshot of our previous capture Form:

What we want is the lower part (tNoteBook, tListView) and some count labels.

We created a CLASS:

  • with the following definition:

     c_display_packetsclass(c_packet_sniffer)
                          m_c_page_controltPageControl;
                          m_c_stats_tab_sheettTabSheet;
                          m_c_line_list_viewtListView;
                          m_c_in_labelm_c_out_labelm_c_in_out_label,
                              m_c_packet_count_labeltLabel;
                          m_list_packetsBoolean;
                          m_c_stats_memotMemo;

                          Constructor create_display_packets(p_nameString;
                              p_c_ownertWinControl);
                          procedure start_capture(p_adapter_indexInteger;
                              p_collect_statisticsBoolean;
                              p_file_nameStringp_list_packetsBoolean);
                          procedure add_list_view_line(p_idp_in_or_out,
                              p_protocolp_sub_protocolp_bytes,
                              p_source_ipp_source_port,
                              p_destination_ipp_destination_portString);
                          procedure display_packet(p_c_packet_snifferc_packet_sniffer);
                          procedure stats_button_click(SendertObject);
                          Destructor DestroyOverride;
                        end// c_display_packets

  • the constructor builds all the controls:

    Constructor c_display_packets.create_display_packets(p_nameString;
        p_c_ownertWinControl);
      var l_c_stats_paneltPanel;
      begin
        Inherited create_packet_sniffer(p_name);

        l_c_stats_panel:= tPanel.Create(p_c_owner);
        with l_c_stats_panel do
        begin
          Parent:= p_c_owner;
          Height:= 21+ 6;
          Align:= alTop;

          // ... the rest of the construction
        end// with l_c_stats_panel do
      end// create_display_packets

    this method which is about 150 lines long has been truncated for this display

  • and the project using the capture class simply calls:

    procedure TForm1.start_Click(SenderTObject);
      begin
        g_c_display_packets:= c_display_packets.create_display_packets('display_packets',
            sniff_panel);

        g_c_display_packets.start_capture(k_default_adapterk_collect_statistics_true
            'c:\log.bin'k_list_packets_true);
      end// connect_Click




We build a small project with a tPanel (the owner and parent of our packet display) and a "star" and "stop" button, and the .ZIP is available. The c_display_packet CLASS could easily be turned into a component, but our main goal being to compare Interbase component we will not do it here.

3.2 - The Interbase Express SELECT  

Let us now write the Interbase Express applications
   create a new application and call il "p_sniff_ibx_select"
   drop a tIbDatabase, a tIbTransaction and link those together.
Double click on tIbDatabase to open the connection editor, and fill in the DatabaseName, User, Password, remove the Login checkbox and hit "Test" to check the connection
   place a tPanel on the Form to display the capture statistics
   place a tButton, create its OnClick event, call it "connect" and write the capture and connection code:

procedure TForm1.connect_Click(SenderTObject);
  var l_log_nameString;
  begin
    if sniff_.Checked
      then begin
          g_c_display_packets:= c_display_packets.create_display_packets('display_packets',
              sniff_panel);

          if log_.Checked
            then begin
                f_create_path(k_local_log_path);
                l_log_name:= k_local_log_pathf_now_to_string'_log_ibx.bin'
              end
            else l_log_name:= '';
          g_c_display_packets.start_capture(0, Truel_log_namek_list_packets_true);
        end;

    IbDatabase1.Open;
  end// connect_Click

   drop an tIbQuery component, link it to IbDatabase1.
   place a tButton, create its OnClick event, call it "select" let it open the table:

const k_table_name'sniffer_table';
      k_sql_select'SELECT * FROM 'k_table_name;

procedure TForm1.select_Click(SenderTObject);
  begin
    DataSource1.Dataset:= Nil;

    with IbQuery1 do
    begin
      Close;

      with Sql do
      begin
        Clear;
        Add(k_sql_select);
        Open;
      end// with Sql
    end// with IbQuery1
  end// select_Click

   compile, run and click:

Here is an example of opening the table:

And when we check "stats", we get the byte counts (we only show the capture window):

You may have noticed that the packet count is not exactly the same at the count in the previous figure: by the time we had copied the figure to the clipboard and had inserted it in this paper, the network had sent some additional packets. We kept the discrepancy to show you that getting an accurate picture might require some quick foot work.



3.3 - Monitoring Ibx

To see which instruction have been sent, we can add an IbSqlMonitor:
   drop a tIbSqlMonitor on Form1. Toggle its Enabled property to True. Create ist OnSql property and let it display each log message:

var g_event_countInteger;

procedure TForm1.IBSQLMonitor1SQL(EventTextStringEventTimeTDateTime);
  begin
    display('= ===== 'IntToStr(g_event_count));
    Inc(g_event_count);
    display('= 'EventText);
  end// IBSQLMonitor1SQL

   here is the monitor display:

This figure show that we can display the Ibx monitoring event together with the packet count. For instance:

= 23 ===== 1
IBTransaction1: [Start transaction]



This simultaneaous monitoring and packet sniffing is interesting because:
  • it shows that the monitoring is performed by the Interbase Express layer, at chosen points, and the information is synthetized to be as useful as possible to the programmer. The goal is not to measure traffic.
  • it also proves how easy it is to intergrate the sniffing class into a project, and display different informations. When we use a separate sniffing tool, we have to note on a piece of paper the timing of the user events and the packet count to try to get an accurate picture. In addition, the possibility to save the captured packets on disk allows us to perform different kind of studies on the data flow off-line, whereas on-line packet analysis would force us to restart the trials again and again.


4 - 1- Sniffing the BDE

We can compare the traffic by using a BDE application:
  • create a new application


We also used direct Interbase Api calls, but will not present the detailed application here, since this would drag us into the isc_xxx programming presentation.



5 - The Results

To have a point of comparison, we computed the rock bottom traffic amount one could expect. This simply is the binary size of record. In our case:
  • s_id INTEGER = 4 bytes
  • s_company CHAR(40) = 40 bytes
  • s_address CHAR(50) = 50 bytes
  • s_contact CHAR(20) = 20 bytes
  • s_amount_due DOUBLE PRECISION = 8 bytes
So each record is 122 bytes long.



We filled the table with 100, 1.000 and 10.000 records, and compared the results for Interbase Express and the BDE:

 records  database  raw  ibx  bde
 100  588 K  12 K  111 (57 K)  58 (24 K)
 1.000  692 K  122 K  268 (199 K)  219 (166 K)
 10.000  1.712 K  1.220 K  1.846 (1.618 K)  1.770 (1.584 K)

In this figure:

  • the "database" figure is the size read in a Windows Explorer
  • "raw" is the amount of the "bare minimum" data size
  • "ibx" is the result of the capture
    • the first number is the packet count (in and out)
    • the second is the packet byte count. This figure is the packet content count (without the header). If you wish to compare this amount to the database size, you must add 54 bytes per packet (14 for Ethernet, 20 for IP and 20 for TCP) which adds a 4% overhead (neglecting the handshake packets, the error packets, packets of smaller size etc).
  • "bde" contains the results for the BDE capture


A couple of points a worth mentioning:
  • when I first performed the 10.000 trial, I kept having 900 K capture logs, whereas the bare minimum is 1.220K. I then stopped displaying the data and added Application.ProcessMessage in the WHILE loop: the result is as displayed above.

    The reason is that when the application processing is too important, the capture misses some packets. Those are mainly at the end of the capture (up to 7000 all packets were recorded, and the end was missing. This was discovered by checking the s_id values in the recorded packets).

    This also demonstrates that using packet capture remains a tricky business.

  • a dump of a single record transfer showed that the true Interbase record sent over the wire was 152 bytes long. This was easily measured by computing the distance between two consecutive records:

     
    51 i 00 E0 18 E5 4D C2 00 90   : <========= 00-90-F5-0F-0C-1F 00-E0-18-E5-4D-C2 
    F5 0F 0C 1F 08 00 ______  : < 
    45 00 03 A4 C3 55 40 00   : <IP        192.168.0.3 192.168.0.2 
    80 06 B2 A8 C0 A8 00 03   : < 
    C0 A8 00 02 ____________  : < 
    0B EA 06 D4 C1 2E 8D 00   : <     TCP  3050 1748 sz=892 
    A4 23 B4 8D 50 18 FD CF   : <          psh,ack, 
    12 FE 00 00 ____________  : <          ack= 8DB423A4, seq= 008D2EC1 
    33 33 33 33 73 60 DC 40   : <          3333s`@< 
    00 00 A0 3A 00 00 00 42   : <          ..:...B< 
    - 
    00 00 00 00 00 00 00 01   : <          ........< 
    4E 04 00 00 00 00 47 6F   : <          N.....Go< 
    6C 64 20 43 6F 61 73 74   : <          ld Coast< 
    20 53 75 70 70 6C 79 20   : <           Supply < 
    20 20 20 20 20 20 20 20   : <                  < 
    20 20 20 20 20 20 20 20   : <                  < 
    20 20 20 20 20 20 00 00   : <                ..< 
    37 2D 37 33 37 36 33 20   : <          7-73763 < 
    4E 61 6E 61 6B 61 77 61   : <          Nanakawa< 
    20 52 6F 61 64 20 20 20   : <           Road   < 
    20 20 20 20 20 20 20 20   : <                  < 
    20 20 20 20 20 20 20 20   : <                  < 
    20 20 20 20 20 20 20 20   : <                  < 
    20 20 00 00 4D 61 72 69   : <            ..Mari< 
    61 20 45 76 65 6E 74 6F   : <          a Evento< 
    73 68 20 20 20 20 20 20   : <          sh      < 
    00 00 00 00 00 00 00 00   : <          ........< 
    00 00 00 00 00 16 DB 40   : <          ......@< 
    00 00 A0 3A 00 00 00 42   : <          ..:...B< 
    - 
    00 00 00 00 00 00 00 01   : <          ........< 
    4F 04 00 00 00 00 55 6E   : <          O.....Un< 
    69 73 63 6F 20 20 20 20   : <          isco    < 
    



In any case, the trial demonstrate that Ibx carries a 30 K overhead. We naturally looked at the content of the Ibx packets on a 1 record table. There were lots of nearly-empty packets. Obviously there was some startup computation performed by Ibx.

At the end, we remembered that we had added the IbMonitor to our application. Changing IbMonitor's Enabled property to False, and even deleting the component form the Form did not change anything. However toggling all IbDatabase TraceFlags to False did the trick: Interbase Express is about 1 K leaner (1.583 K) then the BDE.



So, at the end of the day, the conclusion is the following:

  • Ibx and the BDE have about the same traffic in SELECT statements. This is not too surprising, since all calls are converted to nearly the same isc_xxx Api calls.
  • the use of IbSqlMonitor adds a fixed 30 K overhead in traffic


6 - Improvements

6.1 - Benchmarks

  • all benchmarks can be challenged. We could spend days trying out all kinds of benchmarking schemes and strategies, there is always going to be some user claiming, usually rightly so, that this benchmark does not correspond to the way he is using Interbase. We present here an example, and it will be easy to tweak the code here or there to suit your needs.
In our case
  • we would have to make sure that our trials are not biased by previous experiments. In particular, we should be suspicious of the caches present at many levels (the PC, Interbase, Delphi).
  • time measurements should also be performed without any sniffing in the loop, to avoid any spurious interactions

    In this area, Ibx and the Bde had about the same performance, about a couple of seconds for 100.000 records (on a local 100 MB network). The longest was the ending of the connection (about 7 seconds).

6.2 - Level of Interbase Sniffing

At the client level, we have 3 tracing possibilities:

  • at the first level, the IbSqlMonitor displays informations about the request which are going to be sent to the Interbase Client
  • at the second level, that we named the "proxy" level, you can trap the requests as they are sent to the Interbase Client. For instance, when I was working under Linux I wrote in Delphi a DLL (under Linux it is not named a DLL but it is the same concept). This DLL simply received the request from Ibx, displayed the isc_xxx command AND all its parameters, and forwarded the request to the real Interbase Client. The difference with IbSqlMonitor is that I had all control over what I wanted to display
  • the third level is the network level, which we presented in this paper. We can use general sniffing tools, but have to interpret the raw packet content.


6.3 - Other possibilities

Now that we have the tool, we could study other settings:
  • what is the the impact of the different Interbase Client level or Interbase Server level tunings (cache size, packet size etc)
  • compare the different Interbase versions (Super Server vs Classic, Firebird 1.5 vs Interbase 7.5)
  • analyze the effect of using other Delphi components: dbExpress and the much acclaimed more efficient drivers, or the Borland Data Provider on top of Windows Forms
  • add timing measurements
  • what is the impact of using VARCHAR instead of CHAR (but there we would also add timing measurements, and compare first insert and modifications with longer or shorter values)
  • similar question for parametrized queries vs direct SELECT  
  • forcing some schema loading on our client (by opening tables)
  • using nested tables vs separate master and detail
  • what is the cost of closing and reopening the connection ?
  • an easy one now: using stored procedures and triggers or calling everything over on the Client side. Using a stored procedures for sequence fetching or grabbing the value directly in RDB$DATABASE.
  • transactions. Ah, transactions, that's my favorite one. Just throwing a curve at you: what would be the difference between "SnapShot" and "Read Committed" ?. And what about letting Delphi handling all the transactions (in a single default transaction) versus trying to do it all ourselve, possibly with multiple transactions ?
The list goes on and on. This is an ideal field of investigation for a Master Student looking for an easy thesis subject. With nice graphics all over the place, which always look good at presentation time. And everything can be done in Delphi: the sniffer sources have been published in Delphi in our previous paper, and the creation of the data to measure is part of this paper. tTeeChart to the rescue to draw the lovely graphics.

On a more practical level, I started this sniffing because I did not understand the time taken by some requests. This certainly would be my advice: only dwelve in this area if your are forced to do so because of performance considerations.




7 - Download the Source Code

We placed all the sources for the projects in the following .ZIP files:

Those files contain:
  • the main program (.DPR, .DOF, .RES), the main form (.PAS, .DFM), and any other auxiliary form
  • any .TXT for parameters
  • all units (.PAS) for units
The .ZIPs
  • are self-contained: you will not need any other product (unless expressly mentioned).
  • can be used from any folder (the pathes are RELATIVE)
  • will not modify your PC in any way beyond the path where you placed the .ZIP (no registry changes, no path creation etc).
To use the .ZIP:
  • create or select any folder of your choice
  • unzip the downloaded file
  • using Delphi, compile and execute
To remove the .ZIP simply delete the folder.



As usual:

  • please tell us at fcolibri@felix-colibri.com if you found some errors, mistakes, bugs, broken links or had some problem downloading the file. Resulting corrections will be helpful for other readers
  • we welcome any comment, criticism, enhancement, other sources or reference suggestion. Just send an e-mail to fcolibri@felix-colibri.com.
  • or more simply, enter your (anonymous or with your e-mail if you want an answer) comments below and clic the "send" button
    Name :
    E-mail :
    Comments * :
     

  • and if you liked this article, talk about this site to your fellow developpers, add a link to your links page ou mention our articles in your blog or newsgroup posts when relevant. That's the way we operate: the more traffic and Google references we get, the more articles we will write.



8 - Conclusion

We presented how to use a TPC IP Sniffer to compare Interbase network traffic.




9 - References

  • Ten Things You Can do to Make Interbase Scream
    Bill KARWIN - Borland Conference 1998
    One of the numerous paper about Interbase optimization
  • The Firebird Book
    Helen BORIE - Apress - ISBN 1 59059 279 4
    The most complete book about Interbase programming, at the Sql, and C level. Also very good explanations about the architecture.
  • TCP IP Sniffer the companion paper where we presented the Sniffer capture and display applications



10 - Other Papers with Source and Links

Database
database reverse engineering Extraction of the Database Schema by analyzing the content of the application's .DFMs
sql parser Parsing SQL requests in Delphi, starting from an EBNF grammar for SELECT, INSERT and UPDATE
ado net tutorial a complete Ado Net architectural presentation, and projects for creating the Database, creating Tables, adding, deleting and updating rows, displaying the data in controls and DataGrids, using in memory DataSets, handling Views, updating the Tables with a DataGrid
turbo delphi interbase tutorial develop database applications with Turbo Delphi and Interbase. Complete ADO Net architecture, and full projects to create the database, the Tables, fill the rows, display and update the values with DataGrids. Uses the BDP
bdp ado net blobs BDP and Blobs : reading and writing Blob fields using the BDP with Turbo Delphi
interbase stored procedure grammar Interbase Stored Procedure Grammar : The BNF Grammar of the Interbase Stored Procedure. This grammar can be used to build stored procedure utilities, like pretty printers, renaming tools, Sql Engine conversion or ports
using interbase system tables Using InterBase System Tables : The Interbase / FireBird System Tables: description of the main Tables, with their relationship and presents examples of how to extract information from the schema
eco tutorial Writing a simple ECO application: the UML model, the in memory objects and the GUI presentation. We also will show how to evaluate OCL expressions using the EcoHandles, and persist the data on disc
delphi dbx4 programming the new dbExpress 4 framework for RAD Studio 2007 : the configuration files, how to connect, read and write data, using tracing and pooling delegates and metadata handling
blackfishsql using the new BlackfishSql standalone database engine of RAD Studio 2007 (Win32 and .Net) : create the database, create / fill / read Tables, use Pascal User Defined Functions and Stored Procedures
rave pdf intraweb how to produce PDF reports using Rave, and have an Intraweb site generate and display .PDF pages, with multi-user access
embarcadero er studio Embarcadero ER Studio tutorial: how to use the Entity Relationship tool to create a new model, reverse engineer a database, create sub-models, generate reports, import metadata, switch to Dimensional Model
Web
sql to html converting SQL ascii request to HTML format
simple web server a simple HTTP web Server and the corresponding HTTP web Browser, using our Client Server Socket library
simple cgi web server a simple CGI Web Server which handles HTML <FORM> requests, mainly for debugging CGI Server extension purposes
cgi database browser a CGI extension in order to display and modify a Table using a Web Browser
whois a Whois Client who requests information about owners of IP adresses. Works in batch mode.
web downloader an HTTP tool enabling to save on a local folder an HTML page with its associated images (.GIF, .JPEG, .PNG or other) for archieving or later off-line reading
web spider a Web Spider allowing to download all pages from a site, with custom or GUI filtering and selection.
asp net log file a logging CLASS allowing to monitor the Asp.Net events, mainly used for undesrtanding, debugging and journaling Asp.Net Web applications
asp net viewstate viewer an ASP.NET utility displaying the content of the viewtate field which carries the request state between Internet Explorer and the IIS / CASSINI Servers
rss reader the RSS Reader lets you download and view the content of an .RSS feed (the entry point into somebody's blog) in a tMemo or a tTreeView. Comes complete with an .HTML downloader and an .XML parser
news message tree how to build a tree of the NNTP News Messages. The downloaded messages are displayed in tListBox by message thread (topic), and for each thread the messages are presented in a tTreeVi"ew
threaded indy news reader a NewsReader which presents the articles sorted by thread and in a logical hierarchical way. This is the basic Indy newsreader demo plus the tree organization of messages
delphi asp net portal programming presentation, architecture and programming of the Delphi Asp Net Portal. This is a Delphi version of the Microsoft ASP.NET Starter Kit Web Portal showcase. With detailed schemas and step by step presentation, the Sql scripts and binaries of the Database
delphi web designer a tiny Delphi "RAD Web Designer", which explains how the Delphi IDE can be used to generate .HTML pages using the Palette / Object Inspector / Form metaphor to layout the page content
intraweb architecture the architecture of the Intraweb web site building tool. Explains how Delphi "rad html generator" work, and presents the CLASS organization (UML Class diagrams)
ajax tutorial AJAX Tutorial : writing an AJAX web application. How AJAX works, using a JavaScript DOM parser, the Indy Web Server, requesting .XML data packets - Integrated development project
asp net master pages Asp.Net 2.0 Master Pages : the new Asp.Net 2.0 allow us to define the page structure in a hierarchical way using Master Pages and Content Pages, in a way similar to tForm inheritance
delphi asp net 20 databases Asp.Net 2.0 and Ado.Net 2.0 : displaying and writing InterBase and Blackfish Sql data using Dbx4, Ado.Net Db and AdoDbxClient. Handling of ListBox and GridView with DataSource components
asp net 20 users roles profiles Asp.Net 2.0 Security: Users, Roles and Profiles : Asp.Net 2.0 offers a vaslty improved support for handling security: new Login Controls, and services for managing Users, grouping Users in Roles, and storing User preferences in Profiles
bayesian spam filter Bayesian Spam Filter : presentation and implementation of a spam elimination tool which uses Bayesian Filtering techniques
TCP/IP
tcp ip sniffer project to capture and display the packets travelling on the Ethernet network of your PC.
sniffing interbase traffic capture and analysis of Interbase packets. Creation of a database and test table, and comparison of the BDE vs Interbase Express Delphi components
socket programming the simplest Client Server example of TCP / IP communication using Windows Sockets with Delphi
delphi socket architecture the organization of the ScktComp unit, with UML diagrams and a simple Client Server file transfer example using tClientSocket and tServerSocket
Object Oriented Programming Components
delphi virtual constructor VIRTUAL CONSTRUCTORS together with CLASS references and dynamic Packages allow the separation between a main project and modules compiled and linked in later. The starting point for Application Frameworks and Plugins
delphi generics tutorial Delphi Generics Tutorial : using Generics (parameterized types) in Delphi : the type parameter and the type argument, application of generics, constraints on INTERFACEs or CONSTRUCTORs
UML Patterns
the lexi editor delphi source code of the Gof Editor: Composite, Decorator, Iterator, Strategy, Visitor, Command, with UML diagrams
factory and bridge patterns presentation and Delphi sources for the Abstract Factory and Bridge patterns, used in the Lexi Document Editor case study from the GOF book
gof design patterns delphi source code of the 23 Gof (GAMMA and other) patterns: Composite, Decorator, Iterator, Strategy, Visitor, Command
Debug and Test
Graphic
delphi 3d designer build a 3d volume list, display it in perspective and move the camera, the screen or the volumes with the mouse.
writing a flash player build your own ShockWave Flash movie Player, with pause, custom back and forward steps, snapshots, resizing. Designed for analyzing .SWF demos.
Utilities
the coliget search engine a Full Text Search unit allowing to find the files in a directory satisfying a complex string request (UML AND Delphi OR Patters)
treeview html help viewer Treeview .HTML Help Viewer : the use of a Treeview along with a WebBrowser to display .HTML files alows both structuring and ordering of the help topics. This tool was used to browse the Delphi PRISM Wiki help.
Delphi utilities
delphi net bdsproj structure and analysis of the .BDSPROJ file with the help of a small Delphi .XML parser
dccil bat generator generation of the .BAT for the Delphi DCCIL command line compiler using the .BDSPROJ
dfm parser a Delphi Project analyzing the .DFM file and building a memory representation. This can be used for transformations of the form components
dfm binary to text a Delphi Project converting all .DFM file from a path from binary to ascii format
component to code generate the component creation and initialization code by analyzing the .DFM. Handy to avoid installing components on the Palette when examining new libraries
exe dll pe explorer presents and analyzes the content of .EXE and .DLL files. The starting point for extracting resources, spying .DLL function calls or injecting additional functionalities
dll and process viewer analyze and display the list of running processes, with their associated DLLs and Memory mapped files (Process Walker)
Controls
find memo a tMemo with "find first", "find next", "sort", "save" capabilities
Helper units
windows environment read and write Windows Environment strings
stdin stdout send and receive strings from a GUI application to a CONSOLE application




11 - The author

Felix John COLIBRI works at the Pascal Institute. Starting with Pascal in 1979, he then became involved with Object Oriented Programming, Delphi, Sql, Tcp/Ip, Html, UML. Currently, he is mainly active in the area of custom software development (new projects, maintenance, audits, BDE migration, Delphi Xe_n migrations, refactoring), Delphi Consulting and Delph training. His web site features tutorials, technical papers about programming with full downloadable source code, and the description and calendar of forthcoming Delphi, FireBird, Tcp/IP, Web Services, OOP  /  UML, Design Patterns, Unit Testing training sessions.
Created: nov-04. Last updated: dec-15 - 99 articles, 220 .ZIP sources, 1068 figures
Copyright © Felix J. Colibri   http://www.felix-colibri.com 2004 - 2015. All rigths reserved
Back:    Home  Papers  Training  Delphi developments  Links  Download
the Pascal Institute

Felix J COLIBRI

+ Home
  + articles_with_sources
    + database
      + interbase
      – firebird_trans_simulator
      + sql_server
      + bdp
      – db_refactoring
      – sql_parser
      – sql_to_html
      – sniffing_interbase
      – eco_tutorial
      – dbx4_programming
      – blackfishsql
      – rave_pdf_intraweb
      – rave_reports_tutorial
      – rave_reports_video
      – embarcadero_er/studio
      + firedac
      – bde_unidac_migration
    + web_internet_sockets
    + oop_components
    + uml_design_patterns
    + debug_and_test
    + graphic
    + controls
    + colibri_utilities
    + colibri_helpers
    + delphi
    + firemonkey
    + compilers
  + delphi_training
  + delphi_developments
  + sweet_home
  – download_zip_sources
  + links
Contacts
Site Map
– search :

RSS feed  
Blog