// Use this for initialization public static void Main(String[] args) { // 83 is the base size (in bytes) of a serialized RDTPacket object byte[] receivedData = new byte[Sender.MSS + 83]; int waitingFor = 0; List <RDTPacket> received = new List <RDTPacket>(); bool end = false; // UdpClient fromSender = new UdpClient(new IPEndPoint(IPAddress.Parse("192.168.1.15"), 8080)); while (!end) { Console.WriteLine("Waiting for packet"); // Receive packet IPEndPoint receivedPacket = new IPEndPoint(IPAddress.Parse("192.168.1.15"), 9876); byte [] bytes = fromSender.Receive(ref receivedPacket); // Unserialize to a RDTPacket object RDTPacket packet = (RDTPacket)BinaryFormat.Deserialize(bytes); Console.WriteLine("Packet with sequence number " + packet.getSeq() + " received (last: " + packet.isLast() + " )"); if (packet.getSeq() == waitingFor && packet.isLast()) { waitingFor++; received.Add(packet); Console.WriteLine("Last packet received"); end = true; } else if (packet.getSeq() == waitingFor) { waitingFor++; received.Add(packet); Console.WriteLine("Packed stored in buffer"); } else { Console.WriteLine("Packet discarded (not in order)"); } // Create an RDTAck object RDTAck ackObject = new RDTAck(packet.getSeq()); // Serialize byte[] ackBytes = BinaryFormat.Serialize(ackObject); IPEndPoint ackPacket = new IPEndPoint(IPAddress.Parse("192.168.1.15"), 9876); // Send with some probability of loss Random rand = new Random(); if (rand.Next(2, 3) > PROBABILITY) { fromSender.Send(ackBytes, ackBytes.Length, ackPacket); } else { Console.WriteLine("[X] Lost ack with sequence number " + ackObject.getPacket()); } Console.WriteLine("Sending ACK to seq " + packet.getSeq() + " with " + ackBytes.Length + " bytes"); } Console.ReadKey(); }
// Use this for initialization public static void Main(String[] args) { int lastSent = 0; int waitingForAck = 0; byte[] fileBytes = System.Text.Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVXZ"); Console.WriteLine("Data size: " + fileBytes.Length + " bytes"); int lastSeq = (int)Math.Ceiling((double)fileBytes.Length / MSS) - 1;// lastSent 从 0 开始 标记,这里要减去 1 Console.WriteLine("Number of packets to send: " + lastSeq); string HostName = Dns.GetHostName(); //得到主机名 IPHostEntry IpEntry = Dns.GetHostEntry(HostName); IPAddress receiverAddress = null; for (int i = 0; i < IpEntry.AddressList.Length; i++) { //从IP地址列表中筛选出IPv4类型的IP地址 //AddressFamily.InterNetwork表示此IP为IPv4, //AddressFamily.InterNetworkV6表示此地址为IPv6类型 if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork) { receiverAddress = IpEntry.AddressList[i]; break; } } UdpClient toReceiver = new UdpClient(9876, AddressFamily.InterNetwork); List <RDTPacket> sent = new List <RDTPacket>(); while (true) { // Sending loop while (lastSent - waitingForAck < WINDOW_SIZE && lastSent < lastSeq) { // Array to store part of the bytes to send byte[] filePacketBytes = new byte[MSS]; // Copy segment of data bytes to array Array.Copy(fileBytes, lastSent * MSS, filePacketBytes, 0, MSS); // Create RDTPacket object RDTPacket rdtPacketObject = new RDTPacket(lastSent, filePacketBytes, (lastSent == lastSeq - 1) ? true : false); // Serialize the RDTPacket object byte[] sendData = BinaryFormat.Serialize(rdtPacketObject); Console.WriteLine("Sending packet with sequence number " + lastSent + " and size " + sendData.Length + " bytes"); // Add packet to the sent list sent.Add(rdtPacketObject); // Send with some probability of loss Random rand = new Random(); int num = rand.Next(0, 2); if (num > PROBABILITY) { IPEndPoint IPPoint = new IPEndPoint(receiverAddress, 8080); toReceiver.Send(sendData, sendData.Length, IPPoint); } else { Console.WriteLine("[X] Lost packet with sequence number " + lastSent); } // Increase the last sent lastSent++; } // End of sending while // Byte array for the ACK sent by the receiver byte[] ackBytes = new byte[40]; // Creating packet for the ACK IPEndPoint ack = new IPEndPoint(IPAddress.Any, 0); try { // If an ACK was not received in the time specified (continues on the catch clausule) toReceiver.Client.ReceiveTimeout = TIMER; // Receive the packet byte[] bytes = toReceiver.Receive(ref ack); // Unserialize the RDTAck object RDTAck ackObject = (RDTAck)BinaryFormat.Deserialize(bytes); Console.WriteLine("Received ACK for " + ackObject.getPacket()); // If this ack is for the last packet, stop the sender (Note: gbn has a cumulative acking) if (ackObject.getPacket() == lastSeq) { break; //return; } waitingForAck = Math.Max(waitingForAck, ackObject.getPacket()); } catch (SocketException e) { // then send all the sent but non-acked packets for (int i = waitingForAck; i < lastSent; i++) { // Serialize the RDTPacket object byte[] sendData = BinaryFormat.Serialize(sent[i]); // Create the packet IPEndPoint packet = new IPEndPoint(receiverAddress, 8080); // Send with some probability Random rand = new Random(); if (rand.Next(2, 5) > PROBABILITY) { toReceiver.Send(sendData, sendData.Length, packet); } else { Console.WriteLine("[X_Resending] Lost packet with sequence number " + sent[i].getSeq()); } Console.WriteLine("REsending packet with sequence number " + sent[i].getSeq() + " and size " + sendData.Length + " bytes"); } } } Console.ReadKey(); }