Reputation: 31
I managed to send binary data through TCP using NetworkStream
and Sockets.
My only problem is that when I send larger files like few hundred KB images, they don't get transferred correctly, the half of the image is missing. On the server side I Socket.Send
to transfer data. On the client side I use Socket.BeginReceive
with a 1024
sized buffer that's getting written into a MemoryStream
, later I use new Bitmap(Stream)
to convert that MemoryStream
into an image that can be displayed in a PictureBox
.
What method should I use to avoid data loss?
Edit: code posted
listener = new TcpListener(myAddress, 86);
listener.Start();
TcpClient client = listener.AcceptTcpClient();
ns = client.GetStream();
byte[] buffer = new byte[1024];
while (fileTransfer)
{
ms = new MemoryStream();
do
{
int length = ns.Read(buffer, 0, buffer.Length);
ms.Write(buffer, 0, length);
// with this line added the data loss apparently disappears
System.Threading.Thread.Sleep(1);
} while (ns.DataAvailable);
UpdateData();
ms.Dispose();
System.Threading.Thread.Sleep(10);
}
ns.Dispose();
client.Close();
listener.Stop();
Edit: the data is still corrupt sometime even with the sleep method.
Upvotes: 0
Views: 2608
Reputation: 31
OK I solved it by sending the size of the data before sending the actual data. The reason it didn't work that I wrongly assumed that the transfer was immediate. That's why the Sleep() method in the receiver loop made a difference but did NOT solve the problem. I understand that I can't rely on DataAvailable in this context. Even checking the length of the received data won't work because the client might send data after the loop has finished. Checking the file size (if the data is bigger than the buffer on the receiver side) is the best solution I found so long.
Upvotes: 0
Reputation: 95951
I suggest you change this loop:
do
{
int length = ns.Read(buffer, 0, buffer.Length);
ms.Write(buffer, 0, length);
// with this line added the data loss apparently disappears
System.Threading.Thread.Sleep(1);
} while (ns.DataAvailable);
into:
do
{
int length = ns.Read(buffer, 0, buffer.Length);
ms.Write(buffer, 0, length);
} while (length > 0);
That is, read until the end of data (i.e ns.Read
returns no data). Read
blocks until there are some data or the socket is closed (or some exception is thrown). I removed the useless sleep.
Upvotes: 1
Reputation: 17729
Most likely (at a guess) you are not reading from the stream on the client side correctly.
You need to read the result of the EndReceive ( ) method to see how much data you actually read - it may not be the size of your buffer (1024 bytes in this case)
So:
a) When calling BeginReceive are you passing a callback?
b) If Yes, are you reading the result of this and writing the appropriate amount of bytes into your memory stream?
ie:
public void ReceiveCallback( IAsyncResult result)
{
var buffer = (byte[])result.AsyncState;
int bytesRead = socket.EndReceive();
memoryStream.Write (buffer, 0, bytesRead);//bytesRead may not be 1024!
}
Upvotes: 0