Home > Software engineering >  C# write network stream to binary file -> result corrupted
C# write network stream to binary file -> result corrupted

Time:11-08

I try to capture the entire TCP stream and save it into a binary file. For testing purpose I wrote a smell Python script. This creates the TCP connection and the stream will witten 1:1 to the binary file stream. After this, I can open the saved file with a second program to analyze the captured data. This works with the Python script.

This is the working script

import socket
import sys

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((_ip, _port))

chunks = []
bytes_recd  = 0

f = open("c:\\temp\\trace3.trace", "wb")
cnt = 1500
i = 0
lrcv = 0
print("Logging begins")

while True:
        chunk = s.recv(1024)
        if not chunk:
            print("No Data received")
            break
        f.write(chunk)
        lrcv = lrcv   len(chunk)
        i = i   1
        if i % 50 == 0:
            print("Msg: "   str(i)   ", "   str(lrcv))
        if i >= cnt :
            break
f.close()
s.close()

And here is the "same" in C#. This is compressed to have only the interesting part, without any error handling and so on.

IPAddress ipAddress = IPAddress.Parse(_ip);
IPEndPoint iPEndPoint = new IPEndPoint(ipAddress, _port);
_tcpClient = new TcpClient();
_tcpClient.Connect(iPEndPoint);

FileStream fstream = File.OpenWrite(fname);
using (var stream = _tcpClient.GetStream())
{
    using (var binwriter = new BinaryWriter(fstream, Encoding.Unicode))
    {
        while(true)
        {
            if (!stream.DataAvailable)
            {
                lock (_lock)
                {
                    iState = _started;
                }
                noDataCounter  ;
                if(noDataCounter > _connectionRetries)
                {
                    noDataCounter = 0;
                    throw new Exception($"Timeout while reading data from target {_ip}:{_port}");
                }
                Thread.Sleep(100);
                continue;
            }

            stream.Read(buffer, 0, buffer.Length);
            noDataCounter = 0;

            binwriter.Write(buffer, 0, buffer.Length);
        }

    }
}

If I load the C# captured file, the second program says the file is corrupt. I tried to use the BinaryWriter with several Encodings. Always the same issue. .Net seams to change the incomming data before it will written to the drive. The same issue I had with Python, before I changed the line f = open("c:\temp\trace3.trace", "w") to f = open("c:\temp\trace3.trace", "wb")

At the moment I don't see my mistake. The process is straight forward. Open a TCP connection and save the incoming data without any processing to the hard drive. The stream is a continuous data stream (FYI serialized Java objects).

CodePudding user response:

stream.Read(buffer, 0, buffer.Length);

You are not saving how many bytes are actually read. It should be

var noBytes = stream.Read(buffer, 0, buffer.Length);
binwriter.Write(buffer, 0, noBytes );

This is a common mistake when using raw tcp, and one of the reasons I usually recommend to use some higher level protocol that supports writing messages.

  • Related