/// <summary> /// What is the result of the this request? /// The method will keep waiting/requesting an answer till the answer is received or the timeout is reached /// </summary> /// <param name="message">The request</param> /// <param name="timeOut">The time to wait in milliseconds, 0 means forever</param> /// <returns>The result, null in the case an answer isn't received</returns> public object SendRequest(object message, long timeOut) { Contract.Requires(message != null); Contract.Requires(timeOut >= 0); // Send a request this.requestId++; Packet packet = new Packet("server", this.name, this.requestId.ToString(), message); this.udpMulticast.Send(packet); // Start listening for a reply long preTime = DateTime.Now.ToFileTime(); // Test if the timeout is 0 or the timeout value has run out while (timeOut == 0 || DateTime.Now.ToFileTime() < preTime + (timeOut * 10000)) { // Wait for reply object result = this.udpMulticast.Receive(500); if (result == null) { // No reply - resend... Debug.WriteLine("Client repeats"); this.udpMulticast.Send(packet); } else if (result is Packet) { // A packet was received Packet recPacket = (Packet)result; // Test if the packet is for us if (recPacket.GetReceiverId.Equals(this.name) && recPacket.GetRequestId.Equals(this.requestId.ToString())) { return recPacket.GetMessage; } } } // The timeout value has expired return null; }
/// <summary> /// Listen for calls for this amount of time /// If a request with the same request id is repeated, the reply is repeated /// </summary> /// <param name="timeOut">The time to wait in miliseconds</param> public void ListenForCalls(long timeOut) { Contract.Requires(timeOut >= 0); Contract.Requires(this.RequestHandler != null); // If the server should listen for requests forever bool runForever = timeOut == 0; // The time before the loop was entered long preTime = DateTime.Now.ToFileTime(); // Listen while (runForever || DateTime.Now.ToFileTime() < preTime + (timeOut * 10000)) { // Receive the packet object data; if (runForever) { // The udpMulticast is allowed to block forever data = this.udpMulticast.Receive(0); } else { // The udpMulticast is allowed to block for the time left long timeLeft = ((preTime + (timeOut * 10000)) - DateTime.Now.ToFileTime()) / 10000; data = this.udpMulticast.Receive(timeLeft); } // Test if it's a valid packet if (data == null || !(data is Packet)) { continue; } // Test if the packet is for the server Packet recPacket = (Packet)data; if (recPacket.GetReceiverId.Equals("server")) { // If the packet has been received before if (this.prevPackets.ContainsKey(recPacket.GetSenderId + "#" + recPacket.GetRequestId)) { // Repeat the reply this.udpMulticast.Send(this.prevPackets[recPacket.GetSenderId + "#" + recPacket.GetRequestId]); } else { // The package has not been seen before and we need to generate a response Console.Out.WriteLine("Server sends fresh"); string senderId = recPacket.GetSenderId; string requestId = recPacket.GetRequestId; object resultMessage = this.RequestHandler.Invoke(recPacket.GetMessage); Packet resultPacket = new Packet(senderId, "server", requestId, resultMessage); // Add this request and reply to the list of previous packets this.prevPackets.Add(recPacket.GetSenderId + "#" + recPacket.GetRequestId, resultPacket); this.udpMulticast.Send(resultPacket); } } } }