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
}
}