/* * AsynchronousReader (constructor) * Does the following : * 1. Copy the state object which contains all the data needed for reading to member variable * 2. Create and activate the reading thread */ /**********************************************************************************************//** * Constructor. * * \author Ilan Hindy * \date 29/09/2016 * * \param listenState State of the listen. * **************************************************************************************************/ public AsynchronousReader(SocketStateObject listenState) { this.state = new SocketStateObject(listenState); string sourcePort = ((IPEndPoint)state.workSocket.RemoteEndPoint).Port.ToString(); ReadThread = new Thread(ReadLoop); ReadThread.Name = listenState.process.ea[bp.eak.Name] + " Read port " + sourcePort; ReadThread.Start(); }
/* * Start sending - the main method of the sending */ /**********************************************************************************************//** * Starts a sending. * * \author Ilan Hindy * \date 29/09/2016 * * \param message The message. * \param process The process. * \param channel The channel. * **************************************************************************************************/ public static void StartSending(BaseMessage message, BaseProcess process, BaseChannel channel) { try { // Establish the remote endpoint for the socket. string localAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList.First(f => f.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).ToString(); IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(localAddress), channel.or[bc.ork.DestPort]); // Build the state object SocketStateObject state = new SocketStateObject(); state.process = process; Socket client; //If this is the first time that there is a sending through the channel if (channel.sendingSocket == null) { //Establish the local end point for the socket int localPort = channel.or[bc.ork.SourcePort]; IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse(localAddress), localPort); //Create a new socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //Bind the local address client.Bind(localEndPoint); //Set the socket in the channel and in the state object channel.sendingSocket = client; state.clientSocket = client; // Connect to the remote endpoint. Logger.Log(Logger.LogMode.MainLogAndProcessLogAndMessageTrace, process.GetProcessDefaultName(), "AsynchronousSender.StartSending()", "before BeginConnect()", "", "ProcessSend"); client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), state); state.connectDone.WaitOne(); } else //This is not the first sending from the channel { //Get the socket from the channel and set it in the state object client = channel.sendingSocket; state.clientSocket = client; } // Send test data to the remote device. MessageRouter.ReportMessageSent(process, new object[] { message }); Send(message, state); state.sendDone.WaitOne(); } catch (Exception e) { Logger.Log(Logger.LogMode.MainLogProcessLogAndError, process.GetProcessDefaultName(), "AsynchronousSender.StartSending()", "Error", e.ToString(), "Error"); } }
/* * StartListening * This method listen to new connections n an infinit loop * The loop terminates when the StopFlag of the process is set to true * There is one listener for each process */ /**********************************************************************************************//** * Starts a listening. * * \author Ilan Hindy * \date 29/09/2016 * * \param localPort The local port. * \param process The process. * **************************************************************************************************/ public static void StartListening(int localPort, BaseProcess process) { // Establish the local endpoint for the socket. string localAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList.First(f => f.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).ToString(); IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse(localAddress), localPort); // Create a TCP/IP socket. Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { // Bind the socket to the local endpoint and listen for incoming connections. listener.Bind(localEndPoint); listener.Listen(100); while (true) { // Create state SocketStateObject state = new SocketStateObject(); state.process = process; state.listenSocket = listener; // Set the event to nonsignaled state. state.allDone.Reset(); // Start an asynchronous socket to listen for connections. listener.BeginAccept( new AsyncCallback(AcceptCallback), state); //Wait untill the connection is done state.allDone.WaitOne(); // Check if the process ended it's algorithm Logger.Log(Logger.LogMode.MainLogAndProcessLog, process.GetProcessDefaultName(), "AsynchronousSocketListener.StartListening()", "StopFlag = " + process.StopFlag.ToString(), "", "ProcessReceive"); if (process.StopFlag == true) { Thread.Sleep(100); Logger.Log(Logger.LogMode.MainLogAndProcessLog, process.GetProcessDefaultName(), "AsynchronousSocketListener.StartListening()", "listen thread terminated StopFlag = " + process.StopFlag.ToString(), "", "ProcessReceive"); return; } } } catch (Exception e) { Logger.Log(Logger.LogMode.MainLogProcessLogAndError, process.GetProcessDefaultName(), "AsynchronousSocketListener.StartListening()", e.ToString(), "", "Error"); } }
/**********************************************************************************************//** * Constructor. * * \author Ilan Hindy * \date 29/09/2016 * * \param state The state. * **************************************************************************************************/ public SocketStateObject(SocketStateObject state) { workSocket = state.workSocket; listenSocket = state.listenSocket; process = state.process; clientSocket = state.clientSocket; connectDone = state.connectDone; sendDone = state.sendDone; allDone = state.allDone; sb = new StringBuilder(); buffer = new byte[BufferSize]; connectDone = new ManualResetEvent(false); sendDone = new ManualResetEvent(false); allDone = new ManualResetEvent(false); }
/* * SendCallback * This function is called by the socket when it ended the sending */ /**********************************************************************************************//** * Sends a callback. * * \author Ilan Hindy * \date 29/09/2016 * * \param ar The archive. * **************************************************************************************************/ private static void SendCallback(IAsyncResult ar) { // Retrieve the socket from the state object. SocketStateObject state = (SocketStateObject)ar.AsyncState; Socket client = state.clientSocket; BaseProcess process = state.process; try { // Complete sending the data to the remote device. int bytesSent = client.EndSend(ar); // Signal that all bytes have been sent. state.sendDone.Set(); } catch (Exception e) { Logger.Log(Logger.LogMode.MainLogProcessLogAndError, process.GetProcessDefaultName(), "AsynchronousSender.SendCallback()", e.ToString(), "Error"); } }
/* * ConnectCallback * This function is called by the socket when it ended the connection */ /**********************************************************************************************//** * Connects a callback. * * \author Ilan Hindy * \date 29/09/2016 * * \param ar The archive. * **************************************************************************************************/ private static void ConnectCallback(IAsyncResult ar) { // Retrieve the socket from the state object. SocketStateObject state = (SocketStateObject)ar.AsyncState; Socket client = state.clientSocket; BaseProcess process = state.process; try { // Complete the connection. client.EndConnect(ar); // Signal that the connection has been made. state.connectDone.Set(); } catch (Exception e) { Logger.Log(Logger.LogMode.MainLogProcessLogAndError, process.GetProcessDefaultName(), "AsynchronousSender.ConnectCallback()", e.ToString(), "Error"); } }
/* * Send * This function sends one packet */ /**********************************************************************************************//** * Send this message. * * \author Ilan Hindy * \date 29/09/2016 * * \param message The message. * \param state The state. * **************************************************************************************************/ private static void Send(BaseMessage message, SocketStateObject state) { // Retrieve the socket from the state object. Socket client = state.clientSocket; try { //Logging the send message Logger.Log(Logger.LogMode.MainLogAndProcessLogAndMessageTrace, state.process.GetProcessDefaultName(), "AsynchronousSender.Send()", "SEND", message, ""); // Convert the string data to byte data using ASCII encoding. byte[] byteData = Encoding.ASCII.GetBytes(message.MessageString() + "#"); // Begin sending the data to the remote device. client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), state); } catch (Exception e) { Logger.Log(Logger.LogMode.MainLogProcessLogAndError, state.process.GetProcessDefaultName(), "AsynchronousSender.Send()", e.ToString(), "Error"); } }
/* * AcceptCallback * This function is called by the socket when the connection was established */ /**********************************************************************************************//** * Callback, called when the accept. * * \author Ilan Hindy * \date 29/09/2016 * * \param ar The archive. * **************************************************************************************************/ public static void AcceptCallback(IAsyncResult ar) { // Get the socket that handles the client request (The receive socket). SocketStateObject state = (SocketStateObject)ar.AsyncState; Socket listener = state.listenSocket; Socket handler = listener.EndAccept(ar); try { state.workSocket = handler; //Create asynchronouse reader by the process state.process.AddAsynchronousReader(state); // Signal the main thread to continue. state.allDone.Set(); } catch (Exception e) { Logger.Log(Logger.LogMode.MainLogProcessLogAndError, state.process.GetProcessDefaultName(), "AsynchronousSocketListener.AcceptCallback()", e.ToString(), "Error"); } }