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.