using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Net; using System.Net.Sockets; using System.Threading; namespace UEUserGuide { /// /// Implement a TCP client/listener. /// public class NetworkHelper { /////////////////////////////////////////////////////////////////////// #region Internal fields /// /// IP address. /// private IPAddress _address; /// /// IP port. /// private int _port = -1; /// /// Server instance. /// private TcpListener _server; /// /// Client instance. /// private TcpClient _client; /// /// End point reference. /// private NetworkStream _stream; #endregion Internal fields /////////////////////////////////////////////////////////////////////// #region Static methods /// /// Create a new instance of TcpClient from specified instance. /// This method acts like a copy ctor. /// /// Client reference. /// The new instance on success, null otherwise. private static NetworkHelper Create(TcpClient client) { // Sanity check. if (client == null) { UEUserGuide.Logger.Instance.ErrorLogger("NetworkHelper: Client instance is null."); return null; } return new NetworkHelper(client); } #endregion Static methods /////////////////////////////////////////////////////////////////////// #region ctors /// /// Default ctor. /// public NetworkHelper() { _address = null; _port = -1; _server = null; _client = null; } /// /// Builder ctor used in server part. /// /// private NetworkHelper(TcpClient client) { _client = client; _client.NoDelay = true; _stream = _client.GetStream(); } #endregion ctors /////////////////////////////////////////////////////////////////////// #region INetwork iface implementation /////////////////////////////////////////////////////////////////////// #region Initialization part /// /// Initialize the instance of TCP client or server. /// /// IP address to use for the communication. /// Port number /// true on success, false otherwise. public bool Initialize(string address, int port) { try { _port = port; _address = IPAddress.Parse(address); return true; } catch (Exception e) { Logger.Instance.ErrorLogger("NetworkTcp.Initialize: {0}", e); } return false; } /// /// Uninitialize the current instance. /// /// true on success, false otherwise. public bool Uninitialize() { Close(); return true; } #endregion Initialization part /////////////////////////////////////////////////////////////////////// #region Server methods /// /// Start the TCP server. /// method must be called before. /// public void Start() { _server = new TcpListener(_address, _port); _server.ExclusiveAddressUse = false; _server.Server.NoDelay = true; _server.Start(); // To prevent multiple listener instance. Thread.Sleep(1000); } /// /// Stop the TCP server. /// method must be called before. /// public void Stop() { if (_server != null) { _server.Stop(); _server = null; } } /// /// Accept incoming connection. /// /// New client instance. public NetworkHelper AcceptClient() { TcpClient client = _server.AcceptTcpClient(); return NetworkHelper.Create(client); } #endregion Server methods /////////////////////////////////////////////////////////////////////// #region Client methods /// /// Initiate a connection. /// public void Connect() { if (_client != null) { return; } _client = new TcpClient(); _client.NoDelay = true; _client.Connect(_address, _port); // Get a stream object for reading and writing _stream = _client.GetStream(); } /// /// Initiate a connection with login/password.. /// /// Login to pass. /// Password to pass. public void Connect(string login, string password) { throw new NotImplementedException(); } /// /// Terminate the connection. /// public void Close() { if (_client != null) { try { if (_stream != null) { _stream.Close(); } _client.Close(); } catch { } finally { _client = null; _stream = null; } } } #endregion Client methods /////////////////////////////////////////////////////////////////////// #region Data access methods /// /// Received datas from remote. /// /// The buffer to store the datas. Set to null on error. /// The number of bytes received on success, -1 otherwise. public int Receive(out byte[] buffer) { if (_stream != null) { // read size of the packet first. byte[] length = new byte[sizeof(int)]; _stream.Read(length, 0, length.Length); int totalBytes = BitConverter.ToInt32(length, 0); buffer = new byte[totalBytes]; int readBytes = _stream.Read(buffer, 0, buffer.Length); while (readBytes < totalBytes) { byte[] next = new byte[totalBytes - readBytes]; readBytes += _stream.Read(next, 0, next.Length); buffer.Concat(next); } return buffer.Length; } buffer = null; return -1; } /// /// Received strings from remote. /// /// The buffer to store the strings. Set to null on error. /// The number of bytes received on success, -1 otherwise. public int Receive(out string buffer) { if (_stream != null) { if (_stream.DataAvailable) { byte[] inbuf = new byte[512]; IAsyncResult ar = _stream.BeginRead(inbuf, 0, 512, null, null); int bytesRead = _stream.EndRead(ar); if (ar.IsCompleted) { buffer = System.Text.Encoding.ASCII.GetString(inbuf, 0, bytesRead); return buffer.Length; } } else { buffer = ""; return 0; } } buffer = null; return -1; } /// /// Send data to remote. /// /// Data to send. /// The number of byte to send. /// The number of bytes sent on success, -1 otherwise. public int Send(byte[] buffer, int size) { if (_stream != null) { // Sanity checks. if ((buffer == null) || (size == 0)) { return 0; } // Send size of packet first. byte[] length = BitConverter.GetBytes(size); _stream.Write(length , 0, length.Length); // Send the packet after. _stream.Write(buffer, 0, size); _stream.Flush(); return size; } return -1; } /// /// Send string to remote. /// /// String to send. /// The received string length on success, -1 otherwise. public int Send(string buffer) { if (_stream != null) { // Sanity checks. if (string.IsNullOrEmpty(buffer)) { return 0; } byte[] output = System.Text.Encoding.ASCII.GetBytes(buffer); _stream.Write(output, 0, output.Length); _stream.Flush(); return output.Length; } return -1; } #endregion Data access methods #endregion INetwork iface implementation } }