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
/// DelType: Called when a message is received
public delegate void MESSAGE_HANDLER(CSocketClient pSocket, Int32 iNumberOfBytes);
/// DelType: Called when a connection is closed
public delegate void CLOSE_HANDLER(CSocketClient pSocket);
/// DelType: Called when a socket error occurs
public delegate void ERROR_HANDLER(CSocketClient pSocket, Exception pException);
#endregion
#region private variables
/// RefType: A network stream object
private NetworkStream m_pNetworkStream;
private NetworkStream GetNetworkStream
{
get { return m_pNetworkStream; }
set { m_pNetworkStream = value; }
}
/// RefType: A TcpClient object for socket connection
private TcpClient m_pTcpClient;
private TcpClient GetTcpClient
{
get { return m_pTcpClient; }
set { m_pTcpClient = value; }
}
/// RetType: A callback object for processing recieved socket data
private AsyncCallback m_pCallbackReadMethod;
private AsyncCallback GetCallbackReadMethod
{
get { return m_pCallbackReadMethod; }
set { m_pCallbackReadMethod = value; }
}
/// RetType: A callback object for processing send socket data
private AsyncCallback m_pCallbackWriteMethod;
private AsyncCallback GetCallbackWriteMethod
{
get { return m_pCallbackWriteMethod; }
set { m_pCallbackWriteMethod = value; }
}
/// DelType: A reference to a user supplied function to be called when a socket message arrives
private MESSAGE_HANDLER m_pfnMessageHandler;
private MESSAGE_HANDLER GetMessageHandler
{
get { return m_pfnMessageHandler; }
set { m_pfnMessageHandler = value; }
}
/// DelType: A reference to a user supplied function to be called when a socket connection is closed
private CLOSE_HANDLER m_pfnCloseHandler;
private CLOSE_HANDLER GetCloseHandler
{
get { return m_pfnCloseHandler; }
set { m_pfnCloseHandler = value; }
}
/// DelType: A reference to a user supplied function to be called when a socket error occurs
private ERROR_HANDLER m_pfnErrorHandler;
private ERROR_HANDLER GetErrorHandler
{
get { return m_pfnErrorHandler; }
set { m_pfnErrorHandler = value; }
}
/// SimType: Flag to indicate if the class has been disposed
private Boolean m_bDisposeFlag;
private Boolean IsDisposed
{
get { return m_bDisposeFlag; }
set { m_bDisposeFlag = value; }
}
#endregion
#region public variables
/// RefType: The IpAddress the client is connect to
private String m_strIpAddress;
public String GetIpAddress
{
get { return m_strIpAddress; }
set { m_strIpAddress = value; }
}
/// SimType: The Port to either connect to or listen on
private Int16 m_iPort;
public Int16 GetPort
{
get { return m_iPort; }
set { m_iPort = value; }
}
/// RefType: A reference to a user defined object
private Object m_pUserArg;
public Object GetUserArg
{
get { return m_pUserArg; }
set { m_pUserArg = value; }
}
/// SimType: A raw buffer to capture data comming off the socket
private Byte[] m_bytRawBuffer;
public Byte[] GetRawBuffer
{
get { return m_bytRawBuffer; }
set { m_bytRawBuffer = value; }
}
/// SimType: Size of the raw buffer for received socket data
private Int32 m_iSizeOfRawBuffer;
public Int32 GetSizeOfRawBuffer
{
get { return m_iSizeOfRawBuffer; }
set { m_iSizeOfRawBuffer = value; }
}
#endregion
#region constructor + finialise + dispose
/// Constructor for client support
/// SimType: The size of the raw buffer
/// RefType: A Reference to the Users arguments
/// DelType: Reference to the user defined message handler method
/// DelType: Reference to the user defined close handler method
/// DelType: Reference to the user defined error handler method
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;
}
/// Finialize
~CSocketClient()
{
if (!IsDisposed)
Dispose();
}
/// Dispose
public void Dispose()
{
try
{
// Flag that dispose has been called
IsDisposed = true;
// Disconnect the client from the server
Disconnect();
}
catch
{
}
}
#endregion
#region private methods
/// Called when a message arrives
/// RefType: An async result interface
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();
}
}
/// Called when a message is sent
/// RefType: An async result interface
private void SendComplete(IAsyncResult ar)
{
try
{
// Is the Network Stream object valid
if (GetNetworkStream.CanWrite)
GetNetworkStream.EndWrite(ar);
}
catch (Exception)
{
}
}
#endregion
#region public methods
/// Function used to connect to a server
/// RefType: The address to connect to
/// SimType: The Port to connect to
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);
}
}
/// Function used to disconnect from the server
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;
}
/// Function to send a string to the server
/// RefType: A string to send
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");
}
}
/// Function to send a raw buffer to the server
/// RefType: A Raw buffer of bytes to send
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");
}
}
/// Wait for a message to arrive
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
}
}