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