// // Class: AIS_Telnet // Current CLR: 4.0.30319.296 // System: Microsoft Visual Studio 10.0 // Author: dani // Created: 3/16/2013 12:58:03 PM // // Copyright (c) 2013 Informatikbüro Daniel Schick. All rights reserved. using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Net.Sockets; using log4net; namespace bsmd.AISService.AIS { public class AIS_Telnet { #region private fields private const int BFSIZE = 1024; private NetworkStream tcpStream; private TcpClient tcpSocket; private string currentString = ""; private string hostname; private int port; private DateTime? lastRead; private static ILog _log = LogManager.GetLogger(typeof(AIS_Telnet)); #endregion public AIS_Telnet(string theHostname, int thePort) { this.port = thePort; this.hostname = theHostname; this.Connect(); } #region Properties public bool IsConnected { get { return tcpSocket.Connected; } } public string Hostname { get { return this.hostname; } } public int Port { get { return this.port; } } public string StationName { get; set; } #endregion #region public methods private string ReadCurrentUptoNewline() { int newlineIndex = currentString.IndexOf('\n'); string result = this.currentString.Substring(0, newlineIndex); if (currentString.Length > (newlineIndex + 1)) currentString = currentString.Substring(newlineIndex + 1); else currentString = ""; return result; } public string ReadLine() { string result = ""; if (currentString.IndexOf('\n') >= 0) return ReadCurrentUptoNewline(); byte[] inputBuffer = new byte[1024]; if ((tcpSocket == null) || (!tcpSocket.Connected) || !this.tcpStream.CanRead) this.Connect(); if ((tcpSocket == null) || !tcpSocket.Connected) { System.Threading.Thread.Sleep(30000); // wait 5 mins if connect is unsuccessful return result; } if (this.tcpStream.DataAvailable) { try { int bytesRead = this.tcpStream.Read(inputBuffer, 0, 1024); if (bytesRead > 0) { this.lastRead = DateTime.Now; this.currentString += Encoding.ASCII.GetString(inputBuffer, 0, bytesRead); if (currentString.IndexOf('\n') >= 0) return ReadCurrentUptoNewline(); if (this.currentString.Length > 1024) this.currentString = ""; // truncate to avoid overflow for wrong client data flow } } catch (Exception ex) { _log.ErrorFormat("exception reading from tcp stream: {0}", ex.Message); result = ""; } } else { // wenn die Verbindung wegkracht ist immer noch connected true, aber DataAvailable false // es gibt anscheinend keinen richtig guten Workaround. Hard case: Nach einer Stunde Inaktivität schließt der Client hier die // Verbindung und versucht reconnects. Das bekommt der LS100PortProxy aber nicht immer mit.. Folge sind dann die "stehengebliebenen" // Verbindungen if (lastRead == null) lastRead = DateTime.Now; if ((DateTime.Now - lastRead.Value).TotalSeconds > 600) { this.tcpSocket.Close(); this.tcpSocket = null; _log.Info("closing inactive TcpClient"); this.lastRead = DateTime.Now; // reset timer } System.Threading.Thread.Sleep(250); // wait a bit } return result; } public void Close() { if (this.tcpStream != null) this.tcpStream.Close(); this.tcpSocket.Close(); this.tcpStream.Dispose(); } #endregion public void Connect() { try { if ((this.tcpSocket != null) && (this.tcpSocket.Connected)) return; this.tcpSocket = new TcpClient(this.hostname, this.port); this.tcpStream = tcpSocket.GetStream(); _log.InfoFormat("TCP stream connected ({0}:{1})", this.hostname, this.port); } catch (Exception ex) { _log.WarnFormat("AIS_Telnet: cannot connect to ({0}:{1}) : {2}", this.hostname, this.port, ex.Message); } } } }