using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace SocketSystem
{
class CSocketClient
{
#region delegates
/// <summary> DelType: Called when a message is received </summary>
public delegate void MESSAGE_HANDLER(CSocketClient pSocket, Int32 iNumberOfBytes);
/// <summary> DelType: Called when a connection is closed </summary>
public delegate void CLOSE_HANDLER(CSocketClient pSocket);
/// <summary> DelType: Called when a socket error occurs </summary>
public delegate void ERROR_HANDLER(CSocketClient pSocket, Exception pException);
#endregion
#region private variables
/// <summary> RefType: A network stream object </summary>
private NetworkStream m_pNetworkStream;
private NetworkStream GetNetworkStream
{
get { return m_pNetworkStream; }
set { m_pNetworkStream = value; }
}
/// <summary> RefType: A TcpClient object for socket connection </summary>
private TcpClient m_pTcpClient;
private TcpClient GetTcpClient
{
get { return m_pTcpClient; }
set { m_pTcpClient = value; }
}
/// <summary> RetType: A callback object for processing recieved socket data </summary>
private AsyncCallback m_pCallbackReadMethod;
private AsyncCallback GetCallbackReadMethod
{
get { return m_pCallbackReadMethod; }
set { m_pCallbackReadMethod = value; }
}
/// <summary> RetType: A callback object for processing send socket data </summary>
private AsyncCallback m_pCallbackWriteMethod;
private AsyncCallback GetCallbackWriteMethod
{
get { return m_pCallbackWriteMethod; }
set { m_pCallbackWriteMethod = value; }
}
/// <summary> DelType: A reference to a user supplied function to be called when a socket message arrives </summary>
private MESSAGE_HANDLER m_pfnMessageHandler;
private MESSAGE_HANDLER GetMessageHandler
{
get { return m_pfnMessageHandler; }
set { m_pfnMessageHandler = value; }
}
/// <summary> DelType: A reference to a user supplied function to be called when a socket connection is closed </summary>
private CLOSE_HANDLER m_pfnCloseHandler;
private CLOSE_HANDLER GetCloseHandler
{
get { return m_pfnCloseHandler; }
set { m_pfnCloseHandler = value; }
}
/// <summary> DelType: A reference to a user supplied function to be called when a socket error occurs </summary>
private ERROR_HANDLER m_pfnErrorHandler;
private ERROR_HANDLER GetErrorHandler
{
get { return m_pfnErrorHandler; }
set { m_pfnErrorHandler = value; }
}
/// <summary> SimType: Flag to indicate if the class has been disposed </summary>
private Boolean m_bDisposeFlag;
private Boolean IsDisposed
{
get { return m_bDisposeFlag; }
set { m_bDisposeFlag = value; }
}
#endregion
#region public variables
/// <summary> RefType: The IpAddress the client is connect to </summary>
private String m_strIpAddress;
public String GetIpAddress
{
get { return m_strIpAddress; }
set { m_strIpAddress = value; }
}
/// <summary> SimType: The Port to either connect to or listen on </summary>
private Int16 m_iPort;
public Int16 GetPort
{
get { return m_iPort; }
set { m_iPort = value; }
}
/// <summary> RefType: A reference to a user defined object </summary>
private Object m_pUserArg;
public Object GetUserArg
{
get { return m_pUserArg; }
set { m_pUserArg = value; }
}
/// <summary> SimType: A raw buffer to capture data comming off the socket </summary>
private Byte[] m_bytRawBuffer;
public Byte[] GetRawBuffer
{
get { return m_bytRawBuffer; }
set { m_bytRawBuffer = value; }
}
/// <summary> SimType: Size of the raw buffer for received socket data </summary>
private Int32 m_iSizeOfRawBuffer;
public Int32 GetSizeOfRawBuffer
{
get { return m_iSizeOfRawBuffer; }
set { m_iSizeOfRawBuffer = value; }
}
#endregion
#region constructor + finialise + dispose
/// <summary> Constructor for client support </summary>
/// <param name="iSizeOfRawBuffer"> SimType: The size of the raw buffer </param>
/// <param name="pUserArg"> RefType: A Reference to the Users arguments </param>
/// <param name="pfnMessageHandler"> DelType: Reference to the user defined message handler method </param>
/// <param name="pfnCloseHandler"> DelType: Reference to the user defined close handler method </param>
/// <param name="pfnErrorHandler"> DelType: Reference to the user defined error handler method </param>
public CSocketClient(Int32 iSizeOfRawBuffer, Object pUserArg, MESSAGE_HANDLER pfnMessageHandler,
CLOSE_HANDLER pfnCloseHandler, ERROR_HANDLER pfnErrorHandler)
{
// Create the raw buffer
GetSizeOfRawBuffer = iSizeOfRawBuffer;
GetRawBuffer = new Byte[GetSizeOfRawBuffer];
// Save the user argument
GetUserArg = pUserArg;
// Set the handler methods
GetMessageHandler = pfnMessageHandler;
GetCloseHandler = pfnCloseHandler;
GetErrorHandler = pfnErrorHandler;
// Set the async socket method handlers
GetCallbackReadMethod = new AsyncCallback(ReceiveComplete);
GetCallbackWriteMethod = new AsyncCallback(SendComplete);
// Init the dispose flag
IsDisposed = false;
}
/// <summary> Finialize </summary>
~CSocketClient()
{
if (!IsDisposed)
Dispose();
}
/// <summary> Dispose </summary>
public void Dispose()
{
try
{
// Flag that dispose has been called
IsDisposed = true;
// Disconnect the client from the server
Disconnect();
}
catch
{
}
}
#endregion
#region private methods
/// <summary> Called when a message arrives </summary>
/// <param name="ar"> RefType: An async result interface </param>
private void ReceiveComplete(IAsyncResult ar)
{
try
{
// Is the Network Stream object valid
if (GetNetworkStream.CanRead)
{
// Read the current bytes from the stream buffer
Int32 iBytesRecieved = GetNetworkStream.EndRead(ar);
// If there are bytes to process else the connection is lost
if (iBytesRecieved > 0)
{
try
{
// A message came in send it to the MessageHandler
GetMessageHandler(this, iBytesRecieved);
}
catch
{
}
// Wait for a new message
Receive();
}
else
throw new Exception("Shut Down");
}
}
catch (Exception)
{
try
{
// The connection must have dropped call the CloseHandler
GetCloseHandler(this);
}
catch
{
}
Dispose();
}
}
/// <summary> Called when a message is sent </summary>
/// <param name="ar"> RefType: An async result interface </param>
private void SendComplete(IAsyncResult ar)
{
try
{
// Is the Network Stream object valid
if (GetNetworkStream.CanWrite)
GetNetworkStream.EndWrite(ar);
}
catch (Exception)
{
}
}
#endregion
#region public methods
/// <summary> Function used to connect to a server </summary>
/// <param name="strIpAddress"> RefType: The address to connect to </param>
/// <param name="iPort"> SimType: The Port to connect to </param>
public void Connect(String strIpAddress, Int16 iPort)
{
try
{
if (GetNetworkStream == null)
{
// Set the Ipaddress and Port
GetIpAddress = strIpAddress;
GetPort = iPort;
// Attempt to establish a connection
GetTcpClient = new TcpClient(GetIpAddress, GetPort);
GetNetworkStream = GetTcpClient.GetStream();
// Set these socket options
GetTcpClient.ReceiveBufferSize = 1048576;
GetTcpClient.SendBufferSize = 1048576;
GetTcpClient.NoDelay = true;
GetTcpClient.LingerState = new System.Net.Sockets.LingerOption(false, 0);
// Start to receive messages
Receive();
}
}
catch (System.Net.Sockets.SocketException e)
{
throw new Exception(e.Message, e.InnerException);
}
}
/// <summary> Function used to disconnect from the server </summary>
public void Disconnect()
{
// Close down the connection
if (GetNetworkStream != null)
{
GetNetworkStream.Close();
}
if (GetTcpClient != null)
{
GetTcpClient.Close();
}
// Clean up the connection state
GetNetworkStream = null;
GetTcpClient = null;
}
/// <summary> Function to send a string to the server </summary>
/// <param name="strMessage"> RefType: A string to send </param>
public void Send(String strMessage)
{
if ((GetNetworkStream != null) && (GetNetworkStream.CanWrite))
{
// Convert the string into a Raw Buffer
Byte[] pRawBuffer = System.Text.Encoding.ASCII.GetBytes(strMessage);
// Issue an asynchronus write
GetNetworkStream.BeginWrite(pRawBuffer, 0, pRawBuffer.GetLength(0), GetCallbackWriteMethod, null);
}
else
{
throw new Exception("Socket Closed");
}
}
/// <summary> Function to send a raw buffer to the server </summary>
/// <param name="pRawBuffer"> RefType: A Raw buffer of bytes to send </param>
public void Send(Byte[] pRawBuffer)
{
if ((GetNetworkStream != null) && (GetNetworkStream.CanWrite))
{
// Issue an asynchronus write
GetNetworkStream.BeginWrite(pRawBuffer, 0, pRawBuffer.GetLength(0), GetCallbackWriteMethod, null);
}
else
{
throw new Exception("Socket Closed");
}
}
/// <summary> Wait for a message to arrive </summary>
public void Receive()
{
if ((GetNetworkStream != null) && (GetNetworkStream.CanRead))
{
// Issue an asynchronous read
GetNetworkStream.BeginRead(GetRawBuffer, 0, GetSizeOfRawBuffer, GetCallbackReadMethod, null);
}
else
throw new Exception("Socket Closed");
}
#endregion
}
}