public static string receivestring(Socket bacon, formConsole Console, ASCIIEncoding encoding) { StringBuilder data = new StringBuilder(); byte[] nomnom = new byte[bacon.ReceiveBufferSize]; Console.Write("Receiving."); while (bacon.Available > 0) { bacon.Receive(nomnom); data.Append(encoding.GetString(nomnom).Replace("\0", "")); Console.Write("."); } Console.WriteLine("!\nReceived: " + data.ToString()); return data.ToString(); }
/// <summary> /// Waits for data on the given socket with the given timeout, and optionally prints the progress to the Console. /// </summary> /// <param name="bacon">The socket connected to the remote endpoint</param> /// <param name="timeout">Timeout in milliseconds</param> /// <param name="Console">CedLib formConsole to spam the progress to.</param> /// <returns>bacon. imean- whether or not the wait has timed out.</returns> public static bool waitfordata(Socket bacon, int timeout, formConsole Console) { Console.Write("Waiting for response."); int timewaited = 0; while (bacon.Available == 0 && timewaited < timeout) { Thread.Sleep(1); if ((timewaited % 1000) == 0) { Console.Write("."); } timewaited++; }; Console.WriteLine("!"); if (timewaited > timeout - 1) return false; else return true; }
/// <summary> /// Receives a file using the CedLib protocol. (sender must be using CedLib.Networking.sendfile) /// </summary> /// <param name="bacon">The socket to use, will be disconnected after file is received, but can be reused.</param> /// <param name="FileInfo">The file to save to.</param> /// <param name="contentheader">The CedLib content header as received from the remote party.</param> /// <param name="Console">The CedLib formConsole to spam info to while transferring.</param> public static void receivefile(Socket bacon, FileInfo FileInfo, CedLibContentheader contentheader, formConsole Console) { int chunksize = Globals.chunksize * 1024; Console.WriteLine("Chunksize is set to " + chunksize); byte[] receivebytes = new byte[chunksize]; //If done initializing stuff for the receive, send 'OK!' to signal the start of the transfer Console.WriteLine("Sending response to header"); sendstring(bacon, "OK!\n Continue to send me the file"); if (!waitfordata(bacon, 30000, Console)) throw new Exception("Time out while waiting for sender to begin transfer."); BinaryWriter bwriter = new BinaryWriter(File.Open(FileInfo.FullName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read)); System.Diagnostics.Stopwatch swatch = new System.Diagnostics.Stopwatch(); swatch.Start(); Console.Write(string.Format("Receiving file from {0}..", bacon.RemoteEndPoint)); long receivedcount = 0; int lastreceive = 1; while (lastreceive > 0 && bacon.Connected && receivedcount <= contentheader.ContentLength) { if (bacon.Connected) lastreceive = bacon.Receive(receivebytes, chunksize, SocketFlags.None); else { Console.Write("Remote party disconnected. "); break; } bwriter.Write(receivebytes, 0, lastreceive); bwriter.Flush(); Console.Write("."); receivedcount += lastreceive; } bwriter.Flush(); bwriter.Close(); bool verified = false; swatch.Stop(); bacon.Shutdown(SocketShutdown.Both); bacon.Disconnect(true); Console.WriteLine("Done, verifying MD5.."); if (contentheader.FileSum != "") { string newsum = misc_usefulfunctions.GetMD5HashFromFile(FileInfo.FullName); if (newsum != contentheader.FileSum) throw new Exception(string.Format("File corrupted during transfer! Expected sum {0} But got sum {1}", contentheader.FileSum, newsum)); verified = true; } else Console.WriteLine("Warning: No MD5 summary found in content header, cannot verify data!"); float speedinKB = ((receivedcount / 1024.0f) / (swatch.ElapsedMilliseconds / 1000.0f)); if (verified) Console.WriteLine(string.Format("Verified MD5!\nSummary: received {0} bytes in {1} milliseconds! ({2}KB/s)", new object[] { receivedcount, swatch.ElapsedMilliseconds, speedinKB })); else Console.WriteLine(string.Format("Summary: received {0} bytes in {1} milliseconds! ({2}KB/s)", new object[] { receivedcount, swatch.ElapsedMilliseconds, speedinKB })); }
/// <summary> /// Sends a file using the CedLib protocol to a receiving party (which should also be using CedLib) /// </summary> /// <param name="bacon">Provided socket, must be connected. Will be disconnected after sending is done, however can be reused.</param> /// <param name="FileInfo">The file to send</param> /// <param name="Console">The CedLib console to spam information to.</param> public static void sendfile(Socket bacon, FileInfo FileInfo, formConsole Console) { //First establish the filesize to send and notify the receiver StringBuilder contentheaderbuilder = new StringBuilder(); string filemd5 = misc_usefulfunctions.GetMD5HashFromFile(FileInfo.FullName); contentheaderbuilder.AppendFormat("Contentheader:File\nCedLibProtVersion|:{0}\nContentlength|:{1}\nFileSum|:{2}\nFileName|:{3}", new object[] { CedLib.Globals.netversion, FileInfo.Length, filemd5, FileInfo.Name }); Console.WriteLine("Sending content header"); sendstring(bacon, contentheaderbuilder.ToString()); if (!waitfordata(bacon, 30000, Console)) throw new Exception("Time out while waiting for response to header"); string response = receivestring(bacon, Console); if (response.StartsWith("OK!")) { Console.Write("Sending file.."); BinaryReader breader = new BinaryReader(File.Open(FileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); NetworkStream nstream = new NetworkStream(bacon, FileAccess.Write, false); int blocksize = Globals.chunksize * 1024; Console.WriteLine("Chunksize is set to " + blocksize); System.Diagnostics.Stopwatch swatch = new System.Diagnostics.Stopwatch(); swatch.Start(); byte[] sendbytes; for (long i = 0; i < Math.Ceiling(new decimal(FileInfo.Length / blocksize)) + 1; i++) { sendbytes = breader.ReadBytes(blocksize); nstream.Write(sendbytes, 0, sendbytes.Length); Console.Write("."); } swatch.Stop(); float speedinKB = ((FileInfo.Length / 1024.0f) / (swatch.ElapsedMilliseconds / 1000.0f)); breader.Close(); nstream.Flush(); nstream.Close(); bacon.Shutdown(SocketShutdown.Both); bacon.Disconnect(true); Console.WriteLine(string.Format("Done! Sent {0}bytes in {1} milliseconds.({2}KB/s)", new object[3] { FileInfo.Length, swatch.ElapsedMilliseconds, speedinKB })); } else throw new Exception("Remote endpoint threw error, filetransfer failed.", new Exception(response)); }
/// <summary> /// Receives bytes from a remote party and puts them in a memory stream. (as opposed to a file) /// </summary> /// <param name="bacon">Socket to receive from</param> /// <param name="cHeader">CedLib contentheader (needed for bytescount)</param> /// <param name="Console">The CedLib formConsole to spam relevant info to.</param> /// <returns>Memorystream filled with bytes from remote party.</returns> public static MemoryStream receivebytes(Socket bacon, CedLibContentheader cHeader, formConsole Console) { MemoryStream memstream = new MemoryStream(); int chunksize = 1024 * 1024; byte[] receivebytes = new byte[chunksize]; //If done initializing stuff for the receive, send 'OK!' to signal the start of the transfer Console.WriteLine("Sending response to header"); sendstring(bacon, "OK!\n Continue to send me the bytes"); if (!waitfordata(bacon, 30000, Console)) throw new Exception("Time out while waiting for sender to begin transfer."); System.Diagnostics.Stopwatch swatch = new System.Diagnostics.Stopwatch(); swatch.Start(); Console.Write("Receiving file.."); long receivedcount = 0; int lastreceive = 1; while (lastreceive > 0 && bacon.Connected && receivedcount <= cHeader.ContentLength) { if (bacon.Connected) lastreceive = bacon.Receive(receivebytes, chunksize, SocketFlags.None); else { Console.Write("Remote party disconnected. "); break; } memstream.Write(receivebytes, 0, lastreceive); Console.Write("."); receivedcount += lastreceive; } swatch.Stop(); bacon.Shutdown(SocketShutdown.Both); bacon.Disconnect(true); float speedinKB = ((receivedcount / 1024.0f) / (swatch.ElapsedMilliseconds / 1000.0f)); Console.WriteLine(string.Format("Done! received {0} bytes in {1} milliseconds! ({2}KB/s)", new object[] { receivedcount, swatch.ElapsedMilliseconds, speedinKB })); return memstream; }
/// <summary> /// Sends give nbytes to remote party. /// </summary> /// <param name="bacon">Socket to serve the snacks and bytes over.</param> /// <param name="bytestosend">The snacks and bytes.</param> /// <param name="Console">Cedlib formConsole to spam progress reports to.</param> public static void sendbytes(Socket bacon, byte[] bytestosend, formConsole Console) { //First establish the filesize and a filesum to send and notify the receiver StringBuilder contentheaderbuilder = new StringBuilder(); contentheaderbuilder.AppendFormat("Contentheader:File\nCedLibProtVersion|:{0}\nContentlength|:{1}", new object[] { CedLib.Globals.netversion, bytestosend.Length }); Console.WriteLine("Sending content header"); sendstring(bacon, contentheaderbuilder.ToString()); if (!waitfordata(bacon, 30000, Console)) throw new Exception("Time out while waiting for response to header"); string response = receivestring(bacon, Console); System.Diagnostics.Stopwatch swatch = new System.Diagnostics.Stopwatch(); swatch.Start(); if (response.StartsWith("OK!")) { Console.Write("Sending file.."); NetworkStream nstream = new NetworkStream(bacon, FileAccess.Write, false); nstream.Write(bytestosend, 0, bytestosend.Length); nstream.Flush(); swatch.Stop(); float speedinKB = ((bytestosend.Length / 1024.0f) / (swatch.ElapsedMilliseconds / 1000.0f)); nstream.Close(); bacon.Shutdown(SocketShutdown.Both); bacon.Disconnect(true); Console.WriteLine(string.Format("Done! Sent {0}bytes in {1} milliseconds.({2}KB/s)", new object[3] { bytestosend.Length, swatch.ElapsedMilliseconds, speedinKB })); } else throw new Exception("Remote endpoint threw error, filetransfer failed.", new Exception(response)); }