public void Start(IRequestHandler handler) { while (true) { try { if (Requests.Count > 0 || _requestsBehind.Count > 0) { DataRequest request = Requests.Dequeue(); // Console.WriteLine(Encoder.SerializeObject(request)); if (request != null) { if (request.Type == DataRequest._Type.WRITE) { WriteRequest wr = WriteRequest.Parse(request); if (wr != null) { handler.ProcessWrite(wr); } } } AddRangeAsCalls(handler.GetResponses()); List <Call> batches = new List <Call>(); foreach (Call r in _requestsBehind.Values.ToList()) { lock (_lock) { if (!_currentlySending.Contains(r.ID) && batches.Count < 10) { batches.Add(r); _currentlySending.Add(r.ID); } if (batches.Count >= 10) { break; } } } if (batches.Count > 0) { ProcedureCallBatch rb = new ProcedureCallBatch() { Batch = batches, Sender = null, Completed = null }; _client.StartClient(rb, this); Logger.Write(Logger.Tag.INFO, "Behind: " + _requestsBehind.Count); } } } catch (Exception e) { Logger.Write(Logger.Tag.ERROR, e.ToString()); continue; } } }
private void HandleFailure(ProcedureCallBatch request, MainLoop rh) { Dictionary <string, bool> r0 = new Dictionary <string, bool>(); foreach (Call r1 in request.Batch) { r0.Add(r1.ID, false); } // Activate the responsehandler rh.OnResponse(request, new Response() { Status = r0 }); _notified = true; }
public void OnResponse(ProcedureCallBatch batch, Response response) { batch.Batch.ForEach((r) => { if (response != null && response.Status != null && response.Status.ContainsKey(r.ID) && response.Status[r.ID]) { lock (_lock) { _requestsBehind.Remove(r.ID); Logger.Write(Logger.Tag.INFO, "Successfully transmitted: " + r.ID); } } else { lock (_lock) { _requestsBehind.Add(r.ID, r); } } if (_currentlySending.Contains(r.ID)) { _currentlySending.Remove(r.ID); } }); }
/// <summary> /// Establishes connection to the remote host, sends the request an activates OnResponse on the requesthandler /// </summary> public void StartClient(ProcedureCallBatch request, MainLoop rh) { // Connect to a remote device. _received.Clear(); remoteEP = new IPEndPoint(IPAddress.Parse(Params.NODE_HOST), Params.NODE_PORT); sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { _notified = false; sender.LingerState = _linger; // Establish the remote endpoint for the socket. // This example uses port 11000 on the local computer. // Connect the socket to the remote endpoint. Catch any errors. try { IAsyncResult result = sender.BeginConnect(remoteEP, null, null); bool success = result.AsyncWaitHandle.WaitOne(Params.TIMEOUT, true); if (success && sender.Connected) { sender.EndConnect(result); // Encode the data string into a byte array. byte[] msg = Encoder.EncodeProcedureCallBatch(request); // bool sendSuccess = Task.Run(() => { // Send the data through the socket. int bytesSent = sender.Send(msg); // Data buffer for incoming data. byte[] bytes = new byte[2048 * Params.BATCH_SIZE]; // hope thats enough // byte[] bytes = new byte[10240]; // hope thats enough // Receive the response from the remote device. int bytesRec = sender.Receive(bytes); // if (bytesRec < 1) HandleFailure(request, rh); try { Response response = Encoder.DecodeResponse(Encoding.ASCII.GetString(bytes)); rh.OnResponse(request, response); _notified = true; } catch (Exception e) { Console.WriteLine(e.ToString()); HandleFailure(request, rh); _notified = true; } // }).Wait(Params.TIMEOUT); // if (!_notified && !sendSuccess) HandleFailure(request, rh); } } catch (ArgumentNullException ane) { Logger.Write(Logger.Tag.ERROR, string.Format("ArgumentNullException : {0}", ane.ToString())); } catch (SocketException se) { Logger.Write(Logger.Tag.ERROR, string.Format("ArgumentNullException : {0}", se.ToString())); } catch (Exception e) { Logger.Write(Logger.Tag.ERROR, string.Format("ArgumentNullException : {0}", e.ToString())); } } catch (Exception e) { Logger.Write(Logger.Tag.ERROR, e.ToString()); } finally { try { // Release the socket. sender.Shutdown(SocketShutdown.Both); sender.Close(0); } catch {} } if (!_notified) { HandleFailure(request, rh); } }
public static byte[] EncodeProcedureCallBatch(ProcedureCallBatch request) { return(Encoding.ASCII.GetBytes(JsonConvert.SerializeObject(request, Formatting.None) + "<EOF>")); }