public void AddBytes(int bytes, ByteType typ) { if (typ != ByteType.Sent) { rc.AddBytes((uint)bytes); NetworkReceived += (ulong)bytes; return; } sc.AddBytes((uint)bytes); NetworkSent += (ulong)bytes; }
public void ReadCallback(IAsyncResult ar) { //int fileNameLen = 1; //String content = String.Empty; StateObject tempState = (StateObject)ar.AsyncState; Socket handler = tempState.workSocket; int bytesRead = handler.EndReceive(ar); if (bytesRead <= 0) { return; } counter.AddBytes((uint)bytesRead); if (isFirstPacket) { try { // gets the first byte byte[] firstByte = new byte[1]; firstByte = tempState.buffer.Take(1).ToArray(); // first byte has a value 0 - 255 fileNameLength = Convert.ToInt32(firstByte[0]); // a fileName cannot be more then 255 characters because a byte cannot have have a higher value... if (fileNameLength > 255) { // filename is not valid... // this should not happen, should somehow at least validate the first packet to ensure // it contain the right information... return; //fileNameLength = 255; } // TODO: // check if fileName is valid // if file already exist (conflict) fileName = Encoding.ASCII.GetString(tempState.buffer, 1, fileNameLength); //receivePath += "\\" + fileName; // after the file name comes the size of the file // should be a long // that is 64 bit = 8 byte byte[] fileSizeB = tempState.buffer.Skip(1 + fileNameLength).Take(8).ToArray(); fileSize = BitConverter.ToInt64(fileSizeB, 0); // set total to be received totalBytesToBeReceived = fileNameLength + fileSize + 9; // TODO: // get FileInfo object // TODO: // start download counter, datetime, total filesize to download etc // get MD5 hash or other hash of file // make sure all meta data and other stuff is actually sent // calculate hash of when file has been received and written to a file here // close socket and stop thread when entire file has been written // start timer that will execute an event every 1 sec // that shows mb/s kb/s etc timer = new System.Timers.Timer() { Interval = 1000, Enabled = true }; timer.Elapsed += timer_Elapsed; timer.Start(); } catch (InvalidCastException castError) { // was not able to find file size Console.WriteLine(castError.Message); return; } catch (Exception error) { Console.WriteLine(error.Message); return; } } BinaryWriter writer = null; try { // TODO: // double check that file path is correct // TODO: // only open file while it is not in use // wait until file is ready to be written to if (isFirstPacket) { // old way //writer = new BinaryWriter(File.Open(savePathAndFileName, FileMode.Append)); string savePathAndFileName = receivePath + "\\" + fileName; // creates a thread pool using BlockingCollection // this will allow a queue of max 200 threads waiting to write to the file // if more than 200 threads are created, they are blocked and wait until the ' // queue is free fileWriter = new ParallelFileWriter(savePathAndFileName, 200); // the first packet contain information that should not be written to the file itself so // if first packet then increase the index to size of fileName + one byte // since we increase the index, we need to reduce the count by the same amount // + 1 byte for size of fileName byte // + 8 bytes for 64 bit long with file size // shift = 9 bytes + fileName int shift = fileNameLength + 9; //writer.Write(tempState.buffer, shift, bytesRead - shift); byte[] data = new byte[bytesRead - shift]; Array.Copy(tempState.buffer, shift, data, 0, bytesRead - shift); fileWriter.Write(data); isFirstPacket = false; // set fileName, but do not trigger event FileTransferEvents.filename = fileName; } else { byte[] data = new byte[bytesRead]; Array.Copy(tempState.buffer, 0, data, 0, bytesRead); fileWriter.Write(data); //writer.Write(tempState.buffer, 0, bytesRead); } // TODO: // for each byte that has been read, update download counter // based on time and bytes received both mb/s and percentage downloaded // should be calculated in real time // create event // add to written files totalBytesReceived += bytesRead; // TODO: // check if all bytes has been read and transfer is complete if (totalBytesReceived == totalBytesToBeReceived) { // trigger file received event FileTransferEvents.FileReceived = fileName; // reset connection // set everything back to default and wait for new file resetConnection(); } } catch (Exception error) { Console.WriteLine(error.Message); Thread.Sleep(30); } finally { if (writer != null) { writer.Close(); } // triggers event with long of bytes written //FileTransferEvents.BytesReceived = written; // this method starts a new AsyncCallback(ReadCallback) // and this method is ReadCallback so it works as a recursive method handler.BeginReceive(tempState.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), tempState); //Thread.CurrentThread.Interrupt(); } }
public void sendFile() { //BinaryReader bin = null; FileInfo file = null; // attempt to get read from file Console.WriteLine("Attempting to read from file..."); try { // get file info file = new FileInfo(filePath); // only open file again if it has not already been opened // if the binaryReader is already set, continue where it left off if (bin == null) { bin = new BinaryReader(File.OpenRead(filePath)); } } catch (Exception error) { Console.WriteLine("Error reading file: " + error.Message); return; } // attempt to connect Console.WriteLine("Attempting to connect..."); try { // Create a TCP socket. sendingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //sendingSocket.SendBufferSize = 8192; sendingSocket.SendBufferSize = 10240; //sendingSocket.SendBufferSize = 65536; // Don't allow another socket to bind to this port. // Should perhaps consider this one //listener.ExclusiveAddressUse = true; // Connect the socket to the remote endpoint. sendingSocket.Connect(endPoint); } catch (SocketException socketError) { Console.WriteLine("Error connecting: " + socketError.Message); // cannot connect, attempt to reconnect // reconnect every x ms, 1000 ms = 1 sec // this method will call itself basically (recursive) attemptToReconnect(); return; } catch (Exception error) { Console.WriteLine("Error: " + error.Message); return; } Console.WriteLine(String.Format("Connected to {0}:{1}", endPoint.Address.ToString(), endPoint.Port)); if (isFirstPacket) { // send prebuffer Console.WriteLine("Calculating md5 hash of file..."); sendingSocket.Send(getPreBuffer()); } Console.WriteLine("Sending file."); // trigger event FileTransferEvents.TransferStarted = file.Name; // set amount of bytes to be receieved totalBytesToBeSent = (ulong)file.Length; // start bandwith counter if (counter == null) { totalBytesSent = 0; counter = new BandwidthCounter(); } // start timer to trigger kb/s mb/s progress event timer_calc_speed = new System.Timers.Timer() { Interval = 1000, Enabled = true }; timer_calc_speed.Elapsed += timer_calc_speed_Elapsed; timer_calc_speed.Start(); // create buffer //byte[] buff = new byte[2048]; byte[] buff = new byte[10240]; // loop through file while (totalBytesSent < totalBytesToBeSent) { try { // TODO: // if part of the file has been transfered already // then the connection dropped and then a reconnect happened // make sure the transfer continue where it left off and don't // just start from the beginning again. //sending buff's length. totalBytesSent += (ulong)buff.Length; //p.Sock.Send(bin.ReadBytes(buff.Length)); sendingSocket.Send(bin.ReadBytes(buff.Length)); // add to counter counter.AddBytes((uint)buff.Length); } catch (SocketException socketError) { Console.WriteLine("Error connecting: " + socketError.Message); attemptToReconnect(); return; } catch (Exception error) { Console.WriteLine("Error transfering: " + error.Message); // close file if (bin != null) { bin.Close(); } resetConnection(); return; } finally { } } // close file if (bin != null) { bin.Close(); } resetConnection(); FileTransferEvents.Percentage = 100; Console.WriteLine("File sent"); }
public void ReadCallback(IAsyncResult ar) { StateObject tempState = (StateObject)ar.AsyncState; Socket handler = tempState.workSocket; // handle connection problems int bytesRead = 0; try { bytesRead = handler.EndReceive(ar); } catch (SocketException socketError) { Console.WriteLine("Socket error while transfering: " + socketError.Message); Console.WriteLine("Reseting connection..."); resetConnection(); } catch (Exception error) { Console.WriteLine("Error while transfering: " + error.Message); return; } if (bytesRead <= 0) { return; } // add to counter counter.AddBytes((uint)bytesRead); if (isFirstPacket) { try { // gets the first byte byte[] firstByte = new byte[1]; firstByte = tempState.buffer.Take(1).ToArray(); // first byte has a value 0 - 255 fileNameLength = Convert.ToInt32(firstByte[0]); // a fileName cannot be more then 255 characters because a byte cannot have have a higher value... if (fileNameLength > 255) { // filename is not valid... // this should not happen, should somehow at least validate the first packet to ensure // it contain the right information... return; //fileNameLength = 255; } // TODO: // check if fileName is valid // Windows 1252 encoding Encoding encoding1252 = Encoding.GetEncoding(1252); fileName = encoding1252.GetString(tempState.buffer, 1, fileNameLength); // after the file name comes the size of the file // should be a long // that is 64 bit = 8 byte byte[] fileSizeB = tempState.buffer.Skip(1 + fileNameLength).Take(8).ToArray(); fileSize = BitConverter.ToInt64(fileSizeB, 0); // get md5 hash // md5 hash is 16 bytes = 128 bit md5 = tempState.buffer.Skip(1 + fileNameLength + 8).Take(16).ToArray(); // set total to be received totalBytesToBeReceived = fileNameLength + fileSize + 9 + 16; // TODO: // get FileInfo object // TODO: // start download counter, datetime, total filesize to download etc // get MD5 hash or other hash of file // make sure all meta data and other stuff is actually sent // calculate hash of when file has been received and written to a file here // close socket and stop thread when entire file has been written // start timer that will execute an event every 1 sec // that shows mb/s kb/s etc timer = new System.Timers.Timer() { Interval = 1000, Enabled = true }; timer.Elapsed += timer_Elapsed; timer.Start(); } catch (InvalidCastException castError) { // was not able to find file size Console.WriteLine(castError.Message); return; } catch (Exception error) { Console.WriteLine(error.Message); return; } } BinaryWriter writer = null; try { // TODO: // only open file while it is not in use // wait until file is ready to be written to if (isFirstPacket) { // old way //writer = new BinaryWriter(File.Open(savePathAndFileName, FileMode.Append)); // TODO: // check that file name and path is correct string savePathAndFileName = receivePath + "\\" + fileName; // check if file already exist // if it does, simply append to the file if (File.Exists(savePathAndFileName)) { // TODO: // check if md5 hash of existing file is correct // if so, stop transfer // TODO: // if md5 hash is not the same, check file size of existing file // if its bigger than it's supposed too, remove it // if not, start appending to the file Console.WriteLine("File already exist, appending to file..."); fileWriter = new ParallelFileWriter(savePathAndFileName, 200, true); } else { // creates a thread pool using BlockingCollection // this will allow a queue of max 200 threads waiting to write to the file // if more than 200 threads are created, they are blocked and wait until the ' // queue is free fileWriter = new ParallelFileWriter(savePathAndFileName, 200); } // the first packet contain information that should not be written to the file itself so // if first packet then increase the index to size of fileName + one byte // since we increase the index, we need to reduce the count by the same amount // + 1 byte for size of fileName byte // + 8 bytes for 64 bit long with file size // + 16 bytes for md5 hash // shift = 9 bytes + fileName int shift = fileNameLength + 9 + 16; //writer.Write(tempState.buffer, shift, bytesRead - shift); byte[] data = new byte[bytesRead - shift]; Array.Copy(tempState.buffer, shift, data, 0, bytesRead - shift); fileWriter.Write(data); isFirstPacket = false; // set fileName, but do not trigger event FileTransferEvents.filename = fileName; } else { byte[] data = new byte[bytesRead]; Array.Copy(tempState.buffer, 0, data, 0, bytesRead); fileWriter.Write(data); //writer.Write(tempState.buffer, 0, bytesRead); } // add to written files totalBytesReceived += bytesRead; // check if all bytes has been read and transfer is complete if (totalBytesReceived == totalBytesToBeReceived) { // trigger file received event FileTransferEvents.FileReceived = fileName; // get file location string savePathAndFileName = receivePath + "\\" + fileName; // reset connection // set everything back to default and wait for new file resetConnection(); // close file writer so we can access file again if (writer != null) { writer.Close(); } // complete writing tasks and threads fileWriter.Dispose(); Console.WriteLine("Calculating md5 hash of received file..."); // get md5 hash ChecksumCalc checksum = new ChecksumCalc(); byte[] md5AfterTransfer = checksum.GetMD5Checksum(savePathAndFileName); // check if md5 received is identical to md5 calculated after transfer bool isIdentical = checksum.checkIfHashisIdentical(md5, md5AfterTransfer); if (isIdentical) { // the hash received before the file transfer is identical to the // hash calculated with the new file Console.WriteLine("SUCCESS: md5 hash match the md5 of received file"); } else { // delete file? Console.WriteLine("ERROR: File is corrupt, md5 hash does NOT match the md5 of the file received"); } } } catch (Exception error) { Console.WriteLine(error.Message); Thread.Sleep(30); } finally { if (writer != null) { writer.Close(); } // triggers event with long of bytes written //FileTransferEvents.BytesReceived = written; // this method starts a new AsyncCallback(ReadCallback) // and this method is ReadCallback so it works as a recursive method try { handler.BeginReceive(tempState.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), tempState); } catch (SocketException socketError) { Console.WriteLine("Socket error while transfering: " + socketError.Message); Console.WriteLine("Reseting connection..."); resetConnection(); } catch (Exception error) { Console.WriteLine("Error while transfering: " + error.Message); } } }