using log4net; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Net.Sockets; using System.Text; using System.Threading; namespace bsmd.AIS2Service { internal class SerialTCPReader : IAISThread { private readonly string _host; private readonly uint _port; private readonly ConcurrentQueue _inputQueue; private bool _stopFlag = false; private TcpClient tcpSocket; private Thread _thread; private static readonly ILog _log = LogManager.GetLogger(typeof(SerialTCPReader)); public SerialTCPReader(string host, uint port, ConcurrentQueue inputQueue) { _host = host; _port = port; _inputQueue = inputQueue; } private void ReadData() { try { while (!_stopFlag) { if (this.tcpSocket == null || !this.tcpSocket.Connected) this.Connect(); foreach(string line in ReadLines(this.tcpSocket.GetStream(), Encoding.ASCII)) { _inputQueue.Enqueue(line); if (_stopFlag) return; } } } catch(Exception ex) { _log.ErrorFormat("Something bad has happened: {0}", ex.Message); this.FatalErrorOccurred?.Invoke(this, new EventArgs()); } } private void Connect() { this.tcpSocket = new TcpClient(_host, (int)_port); _log.InfoFormat("TCP stream connected ({0}:{1})", _host, _port); } private static IEnumerable ReadLines(Stream source, Encoding encoding) { using(StreamReader reader = new StreamReader(source, encoding)) { string line; while((line = reader.ReadLine()) != null) { yield return line; } _log.InfoFormat("passed behind yield and closing StreamReader"); } } #region IAISThread implementation public event EventHandler FatalErrorOccurred; public void Start() { if (_thread != null) return; // may not run twice ThreadStart runReader = new ThreadStart(this.ReadData); _thread = new Thread(runReader); _thread.Start(); } public void Stop() { if(_thread == null) return; _stopFlag = true; _thread.Join(); _thread = null; } public string Name { get { return "Serial stream reader"; } } #endregion } }