public UdpMessageInfo(UdpMessageData data, UdpMsgSuccessCallback successCallback, UdpMsgFailureCallback failureCallback, TimeSpan retryTime) { this.data = data; this.successCallback = successCallback; this.failureCallback = failureCallback; endOfRetries = DateTime.UtcNow + retryTime; }
void ScheduleForResend(UdpMessageData msg) { Task t = new Task(async() => { await Task.Delay(5000); //wait 5 seconds if (!ackedMessages.ContainsKey(msg.id)) { DateTime endOfRetries = this.endOfRetries[msg.id]; if (DateTime.UtcNow <= endOfRetries) { messages.Add(msg); //retry } else { FailedToSend?.Invoke(msg.id);//signal failed transmission } } else { //remove if it was acked ackedMessages.TryRemove(msg.id, out msg); endOfRetries.TryRemove(msg.id, out DateTime dt); } }); t.Start(); }
void HandleReceive(IAsyncResult result) { if (running) { IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 0); byte[] bytes = receiver.EndReceive(result, ref endPoint); var data = UdpMessageData.FromBytes(bytes); UdpMessageDataReceived?.Invoke(data); receiver.BeginReceive(HandleReceive, null); } }
protected override void Run() { while (true) { try { UdpMessageData msg = messages.Take(); //using async here because im unsure if sync send can throw threadinterrupted exception byte[] bytes = msg.GetBytes(); sender.BeginSend(bytes, bytes.Length, (ar) => { }, null); ScheduleForResend(msg); } catch (ThreadInterruptedException) { break; //leave } } }
public static UdpMessageData FromBytes(byte[] msgBytes) { byte messageType = msgBytes[0]; UdpMessageData retVal = null; switch (messageType) { case (byte)UdpMessageDataType.Request: retVal = UdpMessageRequestData.FromBytes(msgBytes); break; case (byte)UdpMessageDataType.Answer: retVal = UdpMessageAnswerData.FromBytes(msgBytes); break; default: throw new InvalidOperationException("Unknown message type: " + messageType); } return(retVal); }
/// <summary> /// acknowledge that a message has been answered, so it will not be rescheduled /// </summary> /// <param name="msg"></param> public void Ack(UdpMessageData msg) { ackedMessages[msg.id] = msg; }
public void Send(UdpMessageData msg, DateTime endOfRetries) { messages.Add(msg); }
private void ReceiveQueue_UdpMessageDataReceived(UdpMessageData data) { sendQueue.Ack(data); messages.TryRemove(data.id, out UdpMessageInfo _); }