git_bsmd/AIS/bsmd.AISService/AIS/AIS_Telnet.cs

156 lines
5.1 KiB
C#

//
// 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);
}
}
}
}