C# FileStream reads bytes incorrectly - c#

I am trying to develop an app that will upload large files to a web server running PHP. Almost immediately, I stumbled upon a problem that the file is not split correctly.
Currently I have this piece of code
string adrese = "c:\\directory\\file.jpg";
int garums = 16384;
String ext = Path.GetExtension(adrese);
FileStream file = /*/File.Open(adrese, FileMode.Open);/*/
new FileStream(adrese, FileMode.Open, System.IO.FileAccess.Read);
long fgar = file.Length; //100%
long counter = garums;
first = true;
byte[] chunk = new byte[garums];
while (true)
{
int index = 0;
//long Controll = counter+garums;
while (index < chunk.Length)
{
int bytesRead = file.Read(chunk, index, chunk.Length - index);
if (bytesRead == 0)
{
/*byte[] biti = new byte[index];
for (int i = 0; i < index; i++)
{
biti[i] = chunk[i];
}
chunk = new byte[index];
chunk = biti;*/
break;
}
index += bytesRead;
}
if (index != 0) // Our previous chunk may have been the last one
{
byte[] biti = new byte[index];
for (int i = 0; i < index; i++)
{
biti[i] = chunk[i];
}
chunk = new byte[index];
chunk = biti;
// index is the number of bytes in the chunk
sutam(Convert.ToBase64String(chunk),ext);
}
double procentuali = ((counter * 100) / fgar);
if (procentuali > 99)
{
procentuali = 100;
}
progressBar1.Value = (int)Math.Round(procentuali);
label1.Text = "" + procentuali;
counter = counter+garums;
if (index != garums) // We didn't read a full chunk: we're done
{
return;
}
}
file.Close();
Everything works if I set garums to 1, but who will wait for a year or so to upload a file sized multiple GB's.
I would be pleased if you could tell me what is wrong and how to fix this.

Try this instead to upload in chunks:
private void ConvertToChunks()
{
//Open file
string file = MapPath("~/temp/1.xps");
FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
//Chunk size that will be sent to Server
int chunkSize = 1024;
// Unique file name
string fileName = Guid.NewGuid() + Path.GetExtension(file);
int totalChunks = (int)Math.Ceiling((double)fileStream.Length / chunkSize);
// Loop through the whole stream and send it chunk by chunk;
for (int i = 0; i < totalChunks; i++)
{
int startIndex = i * chunkSize;
int endIndex = (int)(startIndex + chunkSize > fileStream.Length ? fileStream.Length : startIndex + chunkSize);
int length = endIndex - startIndex;
byte[] bytes = new byte[length];
fileStream.Read(bytes, 0, bytes.Length);
ChunkRequest(fileName, bytes);
}
}
private void ChunkRequest(string fileName,byte[] buffer)
{
//Request url, Method=post Length and data.
string requestURL = "http://localhost:63654/hello.ashx";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestURL);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
// Chunk(buffer) is converted to Base64 string that will be convert to Bytes on the handler.
string requestParameters = #"fileName=" + fileName + "&data=" + HttpUtility.UrlEncode( Convert.ToBase64String(buffer) );
// finally whole request will be converted to bytes that will be transferred to HttpHandler
byte[] byteData = Encoding.UTF8.GetBytes(requestParameters);
request.ContentLength = byteData.Length;
Stream writer = request.GetRequestStream();
writer.Write(byteData, 0, byteData.Length);
writer.Close();
// here we will receive the response from HttpHandler
StreamReader stIn = new StreamReader(request.GetResponse().GetResponseStream());
string strResponse = stIn.ReadToEnd();
stIn.Close();
}

Related

transfer byte array by chunk over webservice asmx

I am working on a legacy webservice that are used to transfer zip files between server, it works fine until recently where the size of files become larger, more than 700 mb. This causes exceptions as my console application (client) are not able to receive large byte array send by the webservice at once, so i tried to send and receive the byte array by chunk, but the zip file ended up being corrupt and cannot be unzipped, below is what i have tried, i am a bit unfamiliar with webservice so would appreciate if you guys can point out my mistake or maybe point me to a better solution :
console app(original) :
string saveto = MdlMain.FileName;
object file = (object)serviceSoapClient.GetFile( saveto);
FileStream fileStream = new FileStream(GlobalVariable.FileDirectory + str2, FileMode.Create);
fileStream.Write((byte[])file, 0, Conversions.ToInteger(NewLateBinding.LateGet(file, (Type)null, "Length", new object[0], (string[])null, (Type[])null, (bool[])null)));
fileStream.Flush();
fileStream.Close();
webservice (original) :
public byte[] GetFile( string strFilename)
{
FileStream fileStream = new FileStream(this.DJDownloadPath + strFilename, FileMode.Open, FileAccess.Read);
long length = fileStream.Length;
byte[] array = new byte[checked((int)(length + 1L - 1L) + 1)];
fileStream.Read(array, 0, checked((int)length));
fileStream.Close();
HttpContext.Current.Response.BufferOutput = false;
HttpContext.Current.Response.Buffer = false;
return array;
}
Console app (Modified):
FileStream fileStream= new FileStream(#"D:\example.zip", FileMode.Create);
int totalchunkNo = targetfilesize / 2000000;
int remainder = targetfilesize % 2000000;
if (remainder > 0 && remainder != totalchunkNo)
totalchunkNo++;
for (int i = 1; i <= totalchunkNo; i++)
{
byte[] bytetobeWritten = (byte[])serviceSoapClient.GetFileByChunk(MdlMain.FileName, i);
fileStream.Write(bytetobeWritten, 0, Conversions.ToInteger(NewLateBinding.LateGet(bytetobeWritten, (Type)null, "Length", new object[0], (string[])null, (Type[])null, (bool[])null)));
}
fileStream.Flush();
fileStream.Close();
webservice (Modified):
[WebMethod]
public byte[] GetFileByChunk(string strFilename, int requestChunkNo)
{
FileStream fileStream = new FileStream(this.DJDownloadPath + strFilename, FileMode.Open, FileAccess.Read);
long length = fileStream.Length;
byte[] array = new byte[length];
int incomingOffset = 0;
int chunkSize = 2000000;
fileStream.Read(array, 0, (int)length);
fileStream.Close();
int currentchunkNo = 0;
byte[] outboundBuffer = new byte[chunkSize];
while (incomingOffset < array.Length)
{
int lengthh = Math.Min(outboundBuffer.Length, array.Length - incomingOffset);
Buffer.BlockCopy(array, incomingOffset,
outboundBuffer, 0,
lengthh);
incomingOffset += lengthh;
currentchunkNo++;
if (currentchunkNo == requestChunkNo)
{
return outboundBuffer;
}
}
return null;
}

WaveOut stuttering while another media is playing in another environment

I am working on streaming mp3 in real time using NAudio library. I have prepared a code to do it and it works good in general except while another media is playing in another process (e.g. Youtube, local mp3 players..), . At that time, mp3 is stuttering. I don't know why this is happening. How to solve this problem?
Code to stream in Console Application. Copy paste and you can try it.
static void Main(string[] args)
{
AcmMp3FrameDecompressor decompressor = null;
BufferedWaveProvider provider = null;
WaveFormat mp3format = null;
WaveOut waveOut = new WaveOut();
long size = 0;
byte[] decbuffer = new byte[50 * 1024];
//I am using mp3 links converted by listentoyoutube.com
//But links will be expired, so I didnt put any
string url = "";
string path = Path.Combine(Path.GetTempPath(), "test.mp3");
CheckUrlandCreateTools(url, ref decompressor, ref mp3format, ref size);
FileStream fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite);
HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest;
HttpWebResponse resp = req.GetResponse() as HttpWebResponse;
Stream remote = resp.GetResponseStream();
Mp3Frame frame = null;
MemoryStream ms = null;
byte[] buffer = new byte[1024];
int read = 0;
long offset = 0;
provider = new BufferedWaveProvider(decompressor.OutputFormat);
provider.BufferDuration = TimeSpan.FromSeconds(20);
waveOut.Init(provider);
waveOut.Play();
while (waveOut.PlaybackState == PlaybackState.Playing)
{
if((read = remote.Read(buffer, 0, buffer.Length)) > 0)
fs.Write(buffer, 0, read);
fs.Flush();
ms = new MemoryStream(ReadStreamPartially(fs, offset, 100 * 1024));
try
{
frame = Mp3Frame.LoadFromStream(ms);
if (frame == null)
continue;
}
catch
{
continue;
}
offset += ms.Position;
int decompressed = decompressor.DecompressFrame(frame, decbuffer, 0);
provider.AddSamples(decbuffer, 0, decompressed);
if (IsBufferNearlyFull(provider))
Thread.Sleep(500);
}
}
public static byte[] ReadStreamPartially(System.IO.FileStream stream,
long offset, long count)
{
long originalPosition = stream.Position;
stream.Position = offset;
byte[] readBuffer = new byte[4096];
byte[] total = new byte[count];
int totalBytesRead = 0;
int byteRead;
while ((byteRead = stream.ReadByte()) != -1)
{
Buffer.SetByte(total, totalBytesRead, (byte)byteRead);
totalBytesRead++;
if (totalBytesRead == count)
break;
}
if (totalBytesRead < count)
{
byte[] temp = new byte[totalBytesRead];
Buffer.BlockCopy(total, 0, temp, 0, totalBytesRead);
stream.Position = originalPosition;
return temp;
}
stream.Position = originalPosition;
return total;
}
public static bool IsBufferNearlyFull(BufferedWaveProvider bufferedWaveProvider)
{
return bufferedWaveProvider != null &&
bufferedWaveProvider.BufferLength - bufferedWaveProvider.BufferedBytes
< bufferedWaveProvider.WaveFormat.AverageBytesPerSecond / 4;
}
public static void CheckUrlandCreateTools(string url, ref AcmMp3FrameDecompressor decompressor,
ref WaveFormat format, ref long size)
{
HttpWebRequest req = SendRequest(url, 0, 0);
HttpWebResponse resp = req.GetResponse() as HttpWebResponse;
size = resp.ContentLength;
Stream str = resp.GetResponseStream();
byte[] buffer = new byte[1024];
byte[] storer = new byte[1024 * 100];
int bytesRead = 0;
int total = 0;
while ((bytesRead = str.Read(buffer, 0, buffer.Length)) > 0)
{
Buffer.BlockCopy(buffer, 0, storer, total, bytesRead);
total += bytesRead;
Mp3Frame frame = Mp3Frame.LoadFromStream(new MemoryStream(storer));
if (frame == null) continue;
format = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2,
frame.FrameLength, frame.BitRate);
decompressor = new AcmMp3FrameDecompressor(format);
req.Abort();
resp.Close();
str.Close();
break;
}
}
public static HttpWebRequest SendRequest(string url, long from, long to)
{
HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest;
req.Credentials = CredentialCache.DefaultCredentials;
req.Accept = "*/*";
req.KeepAlive = false;
req.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
req.AllowAutoRedirect = true;
if (to > 0)
req.AddRange(from, to);
return req;
}
}

How to stream an mp3 file using a temporary file?

I am working an Mp3 streamer. To stream mp3 file from url, I want to use a temporary file. But trying to read and write the same file throws IOException for File.ReadAllBytes because the file is in use. How can I get throught this problem?
long pos = 0;
string path = pathtothetempfile;
MemoryStream ms = new MemoryStream();
FileStream fs = new FileStream(path, FileMode.Create,
FileAccess.ReadWrite, FileShare.ReadWrite);
do
{
bytesRead = responseStream.Read(buffer, 0, buffer.Length);
fs.Write(buffer, 0, bytesRead);
fs.Flush();
byte[] tempBuffer = File.ReadAllBytes(path);
pos = ms.Position;
ms = new MemoryStream(tempBuffer);
ms.Position = pos;
frame = Mp3Frame.LoadFromStream(ms);
//....codes....
}
while(bytesRead > 0)
I have found an answer by myself by searching so much. This answer contains NAudio to control the Mp3 and it is RAM friendly by reading stream partially. I am sharing it for other people who has the same problem.
WaveOut waveOut;
AcmMp3FrameDecompressor decompressor;
BufferedWaveProvider provider;
bool firstPlay = true;
public void Play()
{
Task.Run(() =>
{
#region WebRequest creator
HttpWebResponse response = null;
if (avgbytes < 0)
{
HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest;
req.AllowAutoRedirect = true;
req.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0";
response = req.GetResponse() as HttpWebResponse;
contentLength = response.ContentLength;
}
else
response = Helper.CreateAudioWebRequest(url, currentTime, avgbytes)
.GetResponse() as HttpWebResponse;
Stream responseStream = response.GetResponseStream();
#endregion
#region Local Variables
byte[] buffer = new byte[17 * 1024];
byte[] bigBuffer = new byte[response.ContentLength];
int bytesRead = 0;
long pos = 0;
long postotal = 0;
string path = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".mp3";
#endregion
Mp3Frame frame;
FileStream fs = new FileStream(path,
FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
do
{
bytesRead = responseStream.Read(buffer, 0, buffer.Length);
fs.Write(buffer, 0, bytesRead);
fs.Flush();
using (MemoryStream ms = new MemoryStream(ReadPartial(fs, postotal, 1024 * 10)))
{
ms.Position = 0;
frame = Mp3Frame.LoadFromStream(ms);
if (frame == null)
{
continue;
}
pos = ms.Position;
postotal += pos;
}
#region First Play
if (firstPlay)
{
avgbytes = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2,
frame.FrameLength, frame.BitRate).AverageBytesPerSecond;
duration = (int)(response.ContentLength * 1d / avgbytes);
firstPlay = false;
}
#endregion
#region Decompress Frame
if (decompressor == null)
{
decompressor = CreateFrameDecompressor(frame) as AcmMp3FrameDecompressor;
provider = new BufferedWaveProvider(decompressor.OutputFormat);
provider.BufferDuration = TimeSpan.FromSeconds(20);
}
int decompressed = decompressor.DecompressFrame(frame, buffer, 0);
#endregion
#region BufferedWaveProvider Area
if (IsBufferNearlyFull(provider))
{
Thread.Sleep(500);
}
provider.AddSamples(buffer, 0, decompressed);
#endregion
if (provider.BufferedDuration.TotalSeconds >= 2 && waveOut == null)
{
waveOut = new WaveOut();
waveOut.Init(provider);
waveOut.Play();
}
}
while (postotal != contentLength || bytesRead > 0 || waveOut==null ||
(waveOut != null && waveOut.PlaybackState == PlaybackState.Playing));
});
}
public static byte[] ReadStreamPartially(System.IO.Stream stream, long offset, long count)
{
long originalPosition = 0;
if (stream.CanSeek)
{
originalPosition = stream.Position;
stream.Position = offset;
}
try
{
byte[] readBuffer = new byte[4096];
byte[] total = new byte[count];
int totalBytesRead = 0;
int byteRead;
while ((byteRead = stream.ReadByte()) != -1)
{
Buffer.SetByte(total, totalBytesRead, (byte)byteRead);
totalBytesRead++;
if (totalBytesRead == count)
{
stream.Position = originalPosition;
break;
}
}
if (totalBytesRead < count)
{
byte[] temp = new byte[totalBytesRead];
Buffer.BlockCopy(total, 0, temp, 0, totalBytesRead);
stream.Position = originalPosition;
return temp;
}
return total;
}
finally
{
if (stream.CanSeek)
{
stream.Position = originalPosition;
}
}
}
private bool IsBufferNearlyFull(BufferedWaveProvider bufferedWaveProvider)
{
return bufferedWaveProvider != null &&
bufferedWaveProvider.BufferLength - bufferedWaveProvider.BufferedBytes
< bufferedWaveProvider.WaveFormat.AverageBytesPerSecond / 4;
}
private static IMp3FrameDecompressor CreateFrameDecompressor(Mp3Frame frame)
{
WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2,
frame.FrameLength, frame.BitRate);
return new AcmMp3FrameDecompressor(waveFormat);
}

Download a file with .net compact and C#

I am re-developing an app for a scanner used for stocktakes to allow it to work while offline. In order to do so, I need to be able to download a file from a laptop which is acting as a server. I got to a point at which it works, but only downloads that are of size 9.53mb max. How can I tweak the code to allow for larger files. I would need to allow for a maximum size of around 30mb.
Here is my code:
try
{
string full_url = App.prouductUrl + App.stStocktakeId + ".db";
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(full_url);
httpRequest.Credentials = CredentialCache.DefaultCredentials;
HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
System.IO.Stream dataStream = httpResponse.GetResponseStream();
// Dim str As Stream = cdsMobileLibrary2.http_download.getfile(filename)
//50 meg
byte[] inBuf = new byte[10000001];
int bytesToRead = Convert.ToInt32(inBuf.Length);
int bytesRead = 0;
while (bytesToRead > 0)
{
int n = dataStream.Read(inBuf, bytesRead, bytesToRead);
if (n == 0)
{
break; // TODO: might not be correct. Was : Exit While
}
bytesRead += n;
bytesToRead -= n;
}
FileStream fstr = new FileStream(#"\productdb\" + App.stStocktakeId + ".db", FileMode.OpenOrCreate, FileAccess.Write);
fstr.Write(inBuf, 0, bytesRead);
dataStream.Close();
fstr.Close();
string size = loginRes.getFromJSON("size");
FileInfo fi = new FileInfo(#"\productdb\" + App.stStocktakeId + ".db");
MessageBox.Show("File Size is:" + fi.Length + "Compared to:" + size);
}
catch { }

I cant receive anything other than text files

I have tried every solution I could find but nothing seems to work. Anything other than text files becomes corrupted; someone said that TCP can't send more than 8KB, so I tried to fix the problem and I think I did. Now, when I send a text file (no matter what size it is), it reaches perfectly but anything else gets corrupted. I know the code for the cutting is expensive to performance but I am going to think about that later.
Here is my sender code:
private string SendFile(string tosend, string tosendname)
{
ipadd = IPAddress.Parse(textBox2.Text);
ep = new IPEndPoint(ipadd, 6112);
Sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
Sender.Connect(ep);
Thread.Sleep(100);
byte[] filetosend = System.IO.File.ReadAllBytes(tosend);
FileStream fs = new FileStream(tosend, FileMode.Open, FileAccess.Read);
//Read byte from image
fs.Read(filetosend, 0, filetosend.Length);
fs.Flush();
fs.Close();
int countt = filetosend.Count();
int dividedcount = countt / 7000;
Sender.Send(Encoding.ASCII.GetBytes("filesize#" + filetosend.Count().ToString()));
Thread.Sleep(500);
List<byte> cuttedtosend = new List<byte>();
for (int counti = 0; counti < dividedcount; counti++)
{
cuttedtosend = new List<byte>();
for (int index = 0; index < 7000; index++)
{
cuttedtosend.Add(filetosend[(filetosend.Count() - countt) + index]);
}
Sender.Send(cuttedtosend.ToArray());
Thread.Sleep(100);
countt -= 7000;
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Countt = " + countt + "\n"); });
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Counti = " + counti + "\n"); });
}
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Done"); });
cuttedtosend = new List<byte>();
for (int index = filetosend.Count() - countt; index < filetosend.Count(); index++)
{
//richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText(index + "this is 2 \n"); });
cuttedtosend.Add(filetosend[index]);
}
Sender.Send(cuttedtosend.ToArray());
countt -= countt;
return "";
}
And here is my receive code:
private async void StartReceiving()
{
List<byte> neededbytes = new List<byte>();
receivedbyte = new byte[InputForm.s];
Receiver.Bind(new IPEndPoint(IPAddress.Parse("0"), 6112));
Receiver.Listen(1000);
string filename = "Downloadedfile";
bool cont = false;
while (true)
{
Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
Client = Receiver.Accept();
int filesize = 0;
byte[] receivechecker = new byte[100];
Client.Receive(receivechecker);
if(Encoding.ASCII.GetString(receivechecker).Contains("filesize#"))
{
filesize = Convert.ToInt32(Encoding.ASCII.GetString(receivechecker).Remove(0, 9));
Client.Receive(receivechecker);
}
if (Encoding.ASCII.GetString(receivechecker).Contains("#100254#"))
{
string[] splttedtext = Encoding.ASCII.GetString(receivechecker.ToArray()).Split('#');
if (splttedtext[0] == "mess")
{
MessageBox.Show(splttedtext[2]);
}
else if (splttedtext[0] == "filename")
{
//MessageBox.Show(splttedtext[2]);
filename = splttedtext[2];
//filename.Replace(#"\", #"/");
cont = true;
}
}
else
{
List<byte> tosave = new List<byte>();
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText(filesize.ToString() + "\n"); });
int countt = filesize / 7000;
FileStream writer = File.Create("DownloadedFile.jpg");
for (int counti = 0; counti < countt; counti++)
{
byte[] toadd = new byte[7000];
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Counti = " + counti.ToString() + "\n"); });
Client.Receive(toadd);
writer.Write(toadd,0,toadd.Count());
neededbytes.AddRange(toadd);
filesize -= 7000;
}
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText(filesize.ToString() + "\n"); });
byte[] toadds = new byte[filesize];
Client.Receive(toadds);
writer.Write(toadds,0,toadds.Count());
writer.Close();
neededbytes.AddRange(toadds);
filesize -= filesize;
}
}
Thanks in advance :D
Edit:
I just tried Sending a 7mb text file and it reached complete.......
The most immediate problem is that you're saving bytes that you didn't necessarily receive. For example, you have:
for (int counti = 0; counti < countt; counti++)
{
byte[] toadd = new byte[7000];
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Counti = " + counti.ToString() + "\n"); });
Client.Receive(toadd);
writer.Write(toadd,0,toadd.Count());
neededbytes.AddRange(toadd);
filesize -= 7000;
}
The documentation for Receive says that the method will receive up to the number of bytes you request. It's not uncommon for it to return fewer bytes than you requested, especially at the end of the file (since it couldn't receive more than the file length).
You need to write:
var bytesRead = Client.Receive(toadd);
writer.Write(toadd, 0, bytesRead); // only write as many bytes as you've read
In general, your code is pretty convoluted, and you have several other possible problems just waiting to bite you. For example, the code that sends the file size sleeps for 500 ms, which just happens to be enough time for the receiver to read just the number of bytes sent. Without that sleep, your code would fail.
You have code to receive the file name, but no code to send it.
I would suggest that you eliminate the ASCII tags and send things in binary. Below is your rewritten Send method.
private string SendFile(string tosend, string tosendname)
{
ipadd = IPAddress.Parse(textBox2.Text);
ep = new IPEndPoint(ipadd, 6112);
Sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
Sender.Connect(ep);
byte[] filetosend = System.IO.File.ReadAllBytes(tosend);
byte[] filesizeBytes = BitConverter.GetBytes(filetosend.Length);
Sender.Send(filesizeBytes); // sends the length as an integer
// note: You could use Socket.Send(filetosend) here.
// but I'll show an example of sending in chunks.
int totalBytesSent = 0;
while (totalBytesSent < filetosend.Length)
{
int bytesLeft = filetosend.Length - totalBytesSent;
int bytesToSend = Math.Min(bytesLeft, 7000);
Sender.Send(filetosend, totalBytesSent, bytesToSend);
richTextBox1.Invoke((MethodInvoker)delegate
{ richTextBox1.Append(totalBytesSent + " bytes sent\n"); });
totalBytesSent += bytesToSend;
}
richTextBox1.Invoke((MethodInvoker)delegate { richTextBox1.AppendText("Done"); });
return "";
}
The receiver code is similarly simplified:
private async void StartReceiving()
{
Receiver.Bind(new IPEndPoint(IPAddress.Parse("0"), 6112));
Receiver.Listen(1000);
string filename = "Downloadedfile";
bool cont = false;
while (true)
{
Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
Client = Receiver.Accept();
// read the length
byte[] filesizeBytes = new byte[4];
int totalBytesReceived = 0;
while (totalBytesReceived < 4)
{
int bytesRead = Client.Receive(
filesizeBytes, totalBytesReceived, 4-totalBytesReceived);
totalBytesReceived += bytesRead;
}
int filesize = BitConverter.ToInt32(filesizeBytes);
richTextBox1.Invoke((MethodInvoker)delegate
{ richTextBox1.AppendText(filesize.ToString() + "\n"); });
// now read the file
using (FileStream writer = File.Create("DownloadedFile.jpg"))
{
byte[] readBuffer = new byte[7000];
totalBytesReceived = 0;
while (totalBytesReceived < filesize)
{
int bytesToRead = Math.Min(7000, filesize - totalBytesReceived);
int bytesRead = Client.Receive(readBuffer, 0, bytesToRead);
totalBytesRead += bytesRead;
writer.Write(readBuffer, 0, bytesRead);
richTextBox1.Invoke((MethodInvoker)delegate
{ richTextBox1.AppendText("Read " + bytesRead.ToString() + "bytes\n"); });
}
richTextBox1.Invoke((MethodInvoker)delegate
{ richTextBox1.AppendText("Done. " + totalBytesRead.ToString() + " bytes\n"); });
}
}
If you want to send the file name, then I would suggest converting it to UTF8 (Encoding.UTF8.GetBytes(filename)), then send an int (4 bytes) that says how long it is, and then the buffer. To receive it, read the 4-byte filename length like I showed how to read the file size, then that many bytes for the file name, and convert back to a string (Encoding.UTF8.GetString(bytes, 0, filenameLength)).
Please excuse any typos or minor errors in the code. I'm doing this from memory and trying to keep somewhat with your coding style.
i suspect that you are expecting the same blocks that you send to be received; ie that record boundaries will be preserved. This is not so. TCP guarantees that every byte sent will be received and that order is preserved; but you could do 1 large 10k send and receive 10k 1 byte messages.

Categories