// Tries to grab a file and download it to our local machine public void GetFile(string filename) { // Init the get file state Console.WriteLine("Requesting file: {0}", filename); ReceiverState state = ReceiverState.RequestingFile; byte[] checksum = null; UInt32 fileSize = 0; UInt32 numBlocks = 0; UInt32 totalRequestedBlocks = 0; Stopwatch transferTimer = new Stopwatch(); // Small function to reset the transfer state Action ResetTransferState = new Action(() => { state = ReceiverState.RequestingFile; checksum = null; fileSize = 0; numBlocks = 0; totalRequestedBlocks = 0; _blockRequestQueue.Clear(); _blocksReceived.Clear(); transferTimer.Reset(); }); // Main loop _running = true; bool senderQuit = false; bool wasRunning = _running; while (_running) { // Check for some new packets (if there are some) _checkForNetworkMessages(); NetworkMessage nm = (_packetQueue.Count > 0) ? _packetQueue.Dequeue() : null; // In case the sender is shutdown, quit bool isBye = (nm == null) ? false : nm.Packet.IsBye; if (isBye) { senderQuit = true; } // The state switch (state) { case ReceiverState.RequestingFile: // Create the REQF RequestFilePacket REQF = new RequestFilePacket(); REQF.Filename = filename; // Send it byte[] buffer = REQF.GetBytes(); _client.Send(buffer, buffer.Length); // Move the state to waiting for ACK state = ReceiverState.WaitingForRequestFileACK; break; case ReceiverState.WaitingForRequestFileACK: // If it is an ACK and the payload is the filename, we're good bool isAck = (nm == null) ? false : (nm.Packet.IsAck); if (isAck) { AckPacket ACK = new AckPacket(nm.Packet); // Make sure they respond with the filename if (ACK.Message == filename) { // They got it, shift the state state = ReceiverState.WaitingForInfo; Console.WriteLine("They have the file, waiting for INFO..."); } else { ResetTransferState(); // Not what we wanted, reset } } break; case ReceiverState.WaitingForInfo: // Verify it's file info bool isInfo = (nm == null) ? false : (nm.Packet.IsInfo); if (isInfo) { // Pull data InfoPacket INFO = new InfoPacket(nm.Packet); fileSize = INFO.FileSize; checksum = INFO.Checksum; numBlocks = INFO.BlockCount; // Allocate some client side resources Console.WriteLine("Received an INFO packet:"); Console.WriteLine(" Max block size: {0}", INFO.MaxBlockSize); Console.WriteLine(" Num blocks: {0}", INFO.BlockCount); // Send an ACK for the INFO AckPacket ACK = new AckPacket(); ACK.Message = "INFO"; buffer = ACK.GetBytes(); _client.Send(buffer, buffer.Length); // Shift the state to ready state = ReceiverState.PreparingForTransfer; } break; case ReceiverState.PreparingForTransfer: // Prepare the request queue for (UInt32 id = 1; id <= numBlocks; id++) { _blockRequestQueue.Enqueue(id); } totalRequestedBlocks += numBlocks; // Shift the state Console.WriteLine("Starting Transfer..."); transferTimer.Start(); state = ReceiverState.Transfering; break; case ReceiverState.Transfering: // Send a block request if (_blockRequestQueue.Count > 0) { // Setup a request for a Block UInt32 id = _blockRequestQueue.Dequeue(); RequestBlockPacket REQB = new RequestBlockPacket(); REQB.Number = id; // Send the Packet buffer = REQB.GetBytes(); _client.Send(buffer, buffer.Length); // Some handy info Console.WriteLine("Sent request for Block #{0}", id); } // Check if we have any blocks ourselves in the queue bool isSend = (nm == null) ? false : (nm.Packet.IsSend); if (isSend) { // Get the data (and save it SendPacket SEND = new SendPacket(nm.Packet); Block block = SEND.Block; _blocksReceived.Add(block.Number, block); // Print some info Console.WriteLine("Received Block #{0} [{1} bytes]", block.Number, block.Data.Length); } // Requeue any requests that we haven't received if ((_blockRequestQueue.Count == 0) && (_blocksReceived.Count != numBlocks)) { for (UInt32 id = 1; id <= numBlocks; id++) { if (!_blocksReceived.ContainsKey(id) && !_blockRequestQueue.Contains(id)) { _blockRequestQueue.Enqueue(id); totalRequestedBlocks++; } } } // Did we get all the block we need? Move to the "transfer successful state." if (_blocksReceived.Count == numBlocks) { state = ReceiverState.TransferSuccessful; } break; case ReceiverState.TransferSuccessful: transferTimer.Stop(); // Things were good, send a BYE message Packet BYE = new Packet(Packet.Bye); buffer = BYE.GetBytes(); _client.Send(buffer, buffer.Length); Console.WriteLine("Transfer successful; it took {0:0.000}s with a success ratio of {1:0.000}.", transferTimer.Elapsed.TotalSeconds, (double)numBlocks / (double)totalRequestedBlocks); Console.WriteLine("Decompressing the Blocks..."); // Reconstruct the data if (_saveBlocksToFile(filename, checksum, fileSize)) { Console.WriteLine("Saved file as {0}.", filename); } else { Console.WriteLine("There was some trouble in saving the Blocks to {0}.", filename); } // And we're done here _running = false; break; } // Sleep Thread.Sleep(1); // Check for shutdown _running &= !_shutdownRequested; _running &= !senderQuit; } // Send a BYE message if the user wanted to cancel if (_shutdownRequested && wasRunning) { Console.WriteLine("User canceled transfer."); Packet BYE = new Packet(Packet.Bye); byte[] buffer = BYE.GetBytes(); _client.Send(buffer, buffer.Length); } // If the server told us to shutdown if (senderQuit && wasRunning) { Console.WriteLine("The sender quit on us, canceling the transfer."); } ResetTransferState(); // This also cleans up collections _shutdownRequested = false; // In case we shut down one download, but want to start a new one }
public static void StartClient() { // Data buffer for incoming data. byte[] bytes = new byte[1024]; // Connect to a remote device. try { // Establish the remote endpoint for the socket. // This example uses port 11000 on the local computer. IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName()); IPAddress ipAddress = ipHostInfo.AddressList[0]; IPEndPoint remoteEP = new IPEndPoint(ipAddress, 81); bool isNotExit = true; // Create a TCP/IP socket. bool isConnected = false; Socket sender = null; string senddata = ""; Packet packet = new Packet(); while (isNotExit) { // Connect the socket to the remote endpoint. Catch any errors. try { if (!isConnected) { sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sender.Connect(remoteEP); Console.WriteLine("Socket connected to {0}", sender.RemoteEndPoint.ToString()); } isConnected = true; try { if (packet.RequestLength > 0) { packet.AddResponse(System.IO.File.ReadAllText(packet.Request)); } } catch (Exception ex) { packet.AddResponse("No Response"); } // Encode the data string into a byte array. Console.WriteLine("Data sent to Server: " + packet.Response); //Packet SentPacket = new Packet(senddata,PacketType.Response); List <byte> lsb = new List <byte>(); packet.GetBytes(ref lsb); byte[] msg = lsb.ToArray(); //byte[] msg = Encoding.ASCII.GetBytes("http://localhost:8081/"); // Send the data through the socket. int bytesSent = sender.Send(msg); Thread.Sleep(1000); // Receive the response from the remote device. int bytesRec = sender.Receive(bytes); packet = new Packet(bytes); Thread.Sleep(1000); //datarecv = Encoding.ASCII.GetString(bytes, 0, bytesRec); Console.WriteLine("Packet req: {0}", packet.Request); if (!isNotExit) { // Release the socket. sender.Shutdown(SocketShutdown.Both); sender.Close(); } } catch (ArgumentNullException ane) { Console.WriteLine("ArgumentNullException : {0}", ane.ToString()); isNotExit = false; } catch (SocketException se) { Console.WriteLine("Socket Server is not running. Please wait..."); isNotExit = true; Thread.Sleep(5000); } catch (Exception e) { Console.WriteLine("Unexpected exception : {0}", e.ToString()); isNotExit = false; } } } catch (Exception e) { Console.WriteLine(e.Message); } }