delphifreepascallazarusnetcatararat-synapse

Lazarus/FreePascal, Synapse send file to TCPBlockSocket


I tried to make an analogue nc (netcat) tool. Open file and send it in to TCP socket.

client (sender) side

procedure TForm1.SpeedButton3Click(Sender: TObject);
var Client:TTCPBlockSocket;
    FS: TFileStream;
begin
  Client:=TTCPBlockSocket.Create;
  Client.RaiseExcept:=True;
  Client.Connect('192.168.1.95','9999');
  FS:=TFileStream.Create('/tmp/test_print.pdf',fmOpenRead);
  FS.Position:=0;
  Client.SendStream(FS);
  FS.Free;
  Client.CloseSocket;
  Client.Free;
end;        

server (reciever) side

nc -l 192.168.1.95 9999 > test.pdf

After run i get test.pdf but md5sum not valid

fe2e5d86acd267ca39a9c15c456e1be0  /tmp/test_print.pdf
34d755aa81d72f525a5e691e98bed283  test.pdf

size is differ too

-rw-rw---- 1 user1 DomainUsers 46444 Июн  8 17:11 /tmp/test_print.pdf
-rw-r--r-- 1 user1 DomainUsers 46448 Июн 11 15:40 test.pdf

What i do wrong? Where is my mistake?

p.s. Excess 4 bytes at the beginning of test.pdf (6c,b5,00,00)

[user1@pandora6 /tmp]$ hexdump -C test.pdf | head -5
00000000  6c b5 00 00 25 50 44 46  2d 31 2e 34 0a 25 c7 ec  |l...%PDF-1.4.%..|
00000010  8f a2 0a 34 20 30 20 6f  62 6a 0a 3c 3c 2f 4c 69  |...4 0 obj.<</Li|
00000020  6e 65 61 72 69 7a 65 64  20 31 2f 4c 20 34 36 34  |nearized 1/L 464|
00000030  34 34 2f 48 5b 20 34 33  39 36 38 20 31 34 32 5d  |44/H[ 43968 142]|
00000040  2f 4f 20 36 2f 45 20 34  33 39 36 38 2f 4e 20 31  |/O 6/E 43968/N 1|

[user1@pandora6 /tmp]$ hexdump -C /tmp/test_print.pdf | head -5
00000000  25 50 44 46 2d 31 2e 34  0a 25 c7 ec 8f a2 0a 34  |%PDF-1.4.%.....4|
00000010  20 30 20 6f 62 6a 0a 3c  3c 2f 4c 69 6e 65 61 72  | 0 obj.<</Linear|
00000020  69 7a 65 64 20 31 2f 4c  20 34 36 34 34 34 2f 48  |ized 1/L 46444/H|
00000030  5b 20 34 33 39 36 38 20  31 34 32 5d 2f 4f 20 36  |[ 43968 142]/O 6|
00000040  2f 45 20 34 33 39 36 38  2f 4e 20 31 2f 54 20 34  |/E 43968/N 1/T 4|

Solution

  • Well... Hex 00 00 B5 6C (your extra bytes in reverse) is equal to 46444. So my guess is that TFileStream or SendStream sends the number of bytes it wants to send before the actual data.

    Looking at the code of Synapse there is the function:

    procedure TBlockSocket.InternalSendStream(const Stream: TStream; WithSize, Indy: boolean);
    

    And SendStream calls it like this:

      InternalSendStream(Stream, true, false);
    

    So the WithSize is true and the size of the stream is send before the actual data.

    If you use SendStreamRaw all is send without the size in front of it.

    procedure TForm1.SpeedButton3Click(Sender: TObject);
    var Client:TTCPBlockSocket;
        FS: TFileStream;
    begin
      Client:=TTCPBlockSocket.Create;
      Client.RaiseExcept:=True;
      Client.Connect('192.168.1.95','9999');
      FS:=TFileStream.Create('/tmp/test_print.pdf',fmOpenRead);
      FS.Position:=0;
      Client.SendStreamRAW(FS);
      FS.Free;
      Client.CloseSocket;
      Client.Free;
    end;