Monday, August 18, 2014

c# socket library core class with usage chat e.g

- some using class -

public class ArrList
    {
        private ArrayList _Key = new ArrayList();
        private ArrayList _Comment = new ArrayList();
        private ArrayList _List = new ArrayList();

        public object this[int index]
        {
            get { return _List[index]; }
        }

        public object this[string key]
        {
            get { return _List[_Key.IndexOf(key)]; }
        }

        public string this[object data]
        {
            get { return (string)_Key[_List.IndexOf(data)]; }
        }

        public int Count
        {
            get { return _List.Count; }
        }

        public int Length
        {
            get { return _List.Count; }
        }

        public bool Add(string key, object data, object comment)
        {
            if (_Key.IndexOf(key) < 0)
            {
                _List.Add(data);
                _Comment.Add(comment);
                _Key.Add(key);
                return true;
            }
            else return false;
        }

        public bool Add(string key, object data)
        {
            if (_Key.IndexOf(key) < 0)
            {
                _List.Add(data);
                _Comment.Add(null);
                _Key.Add(key);
                return true;
            }
            else return false;
        }

        public bool Add(object data)
        {
            if (_Key.IndexOf(_List.Count.ToString()) < 0)
            {
                _List.Add(data);
                _Comment.Add(null);
                _Key.Add((_List.Count - 1).ToString());
                return true;
            }
            else return false;
        }

        public object Get(int index)
        {
            return _List[index];
        }

        public object Get(string key)
        {
            try
            {
                return _List[_Key.IndexOf(key)];
            }
            catch { return null; }
        }

        public string Get(object data)
        {
            try
            {
                return (string)_Key[_List.IndexOf(data)];
            }
            catch { return null; }
        }

        public bool Remove(object data)
        {
            int nd = _List.IndexOf(data);
            if (nd < 0) return false;
            else
            {
                _List.RemoveAt(nd);
                _Comment.RemoveAt(nd);
                _Key.RemoveAt(nd);
                return true;
            }
        }

        public bool Remove(string key)
        {
            int nd = _Key.IndexOf(key);
            if (nd < 0) return false;
            else
            {
                _List.RemoveAt(nd);
                _Comment.RemoveAt(nd);
                _Key.RemoveAt(nd);
                return true;
            }
        }

        public bool Remove(int index)
        {
            if (index < 0 || _List.Count <= index) return false;
            else
            {
                _List.RemoveAt(index);
                _Comment.RemoveAt(index);
                _Key.RemoveAt(index);
                return true;
            }
        }

        public int IndexOf(string key)
        {
            return _Key.IndexOf(key);
        }

        public int IndexOf(object data)
        {
            return _List.IndexOf(data);
        }

        public void Clear()
        {
            _List.Clear();
            _Comment.Clear();
            _Key.Clear();
        }

        public ArrList()
        { }
    }



namespace SocketLibraryCore
{
    /// <summary>
    /// Холбоосоор дамжих өгөгдлийг хүлээн авагч
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="data"></param>
    public delegate void SocketHandler(ClientSocketJob sender, object data);
    /// <summary>
    /// Холбоосын үйлдэл бүрийг мэдэгдэгч
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="msg"></param>
    public delegate void SocketMessageHandler(ClientSocketJob sender, SocketCommandBlock msg);

    [Serializable]
    public enum SocketDataAccess
    {
        Accept = 0,
        Sent = 1,
        Receive = 2,
        ServerStop = 3,
        ServerStart = 4,
        ClientStop = 5,
        ClientStart = 6,
        Log = 7,
        Error = 8
    }

    [Serializable]
    public class SocketCommandBlock
    {
        public string DataCommand { get; set; }
        public string DataString { get; set; }
        public object DataBuffer { get; set; }
        public long DataResult { get; set; }
        public SocketDataAccess DataAccess { get; set; }

        public SocketCommandBlock()
        {
            DataAccess = SocketDataAccess.Log;
        }
    }
   
    /// <summary>
    /// Сервер эсвэл клиент холболт
    /// </summary>
    public class SocketLib
    {
        #region Control Methods

        public event SocketMessageHandler MsgRecieved;
        public void CallMsgRecieved(ClientSocketJob sender, SocketCommandBlock msg)
        {
            if (MsgRecieved != null) MsgRecieved.Invoke(sender, msg);
        }

        public event SocketHandler DataRecieved;
        public void CallDataRecieved(ClientSocketJob sender, object data)
        {
            if (DataRecieved != null) DataRecieved.Invoke(sender, data);
        }

        public int SendToClient(int index, object data)
        {
            var sender = (ClientSocketJob)_ClientList[index];
            return SendToClient(sender, data);
        }
        public int SendToClient(ClientSocketJob sender, object data)
        {
            if (sender != null) return sender.DataSend(data);
            else return 0;
        }
        public List<int> SendToAll(object data, ClientSocketJob ignoreJob = null)
        {
            List<int> list = new List<int>();
            int l = _ClientList.Count;
            for (int i = 0; i < l; i++)
            {
                var job = (_ClientList[i] as ClientSocketJob);
                if (ignoreJob == null || job.JobIndex != ignoreJob.JobIndex)
                {
                    var ret = SendToClient(job, data);
                    list.Add(ret);
                }
            }
            return list;
        }
        public int SendToServer(object data)
        {
            //ClientSocketJob is bridge for server connection
            return (_ClientList[0] as ClientSocketJob).DataSend(data);
        }
        public void Stop(ClientSocketJob sender, object data)
        {
            sender.Stop();
        }
        public void Stop()
        {
            if (_IsServer)
                this.Desconnect();
            else
            {
                if (_ClientList.Count > 0)
                {
                    (_ClientList[0] as ClientSocketJob).Stop();
                }
            }
        }

        #endregion Control Methods

        #region Properties

        private bool _ClientDistinct = true;
        public bool ClientDistinct
        {
            get { return _ClientDistinct; }
            set { _ClientDistinct = value; }
        }
        private Thread _ServerThread;
        private TcpListener _Server;
        private string _HostName = "127.0.0.1";
        public string HostName
        {
            get { return _HostName; }
        }
        private int _PortNumber = 1986;
        public int PortNumber
        {
            get { return _PortNumber; }
        }
        private bool _IsServer;
        public bool IsServer
        {
            get { return _IsServer; }
        }
        private bool _IsRunning;
        public bool IsRunning
        {
            get { return _IsRunning; }
        }

        //
        private ArrList _ClientList;
        public ArrList ClientList
        {
            get { return _ClientList; }
        }
        public ClientSocketJob Me
        {
            get
            {
                return (_IsServer == true) ? null :
                    ((_ClientList == null || _ClientList.Count == 0) ? null : (ClientSocketJob)_ClientList[0]);
            }
        }
        private long _ClientJobCount;
        public long ClientJobCount
        {
            get { return _ClientJobCount; }
        }

        #endregion Properties

        /// <summary>
        /// Сервер эсвэл клиент холболтын ажлын класс
        /// </summary>
        /// <param name="isServer">Сервер талын холбоос эсэх</param>
        /// <param name="isDistinct">Клиент талын хаяг давхардах эсэх</param>
        public SocketLib(bool isServer, bool isDistinct)
        {
            _ClientJobCount = 0;
            _ClientList = new ArrList();
            _IsServer = isServer;
            _ClientDistinct = isDistinct;
        }

        /// <summary>
        /// Холболтыг эхлүүлэх
        /// </summary>
        /// <param name="HostName"></param>
        /// <param name="PortNumber"></param>
        public void Connect(string HostName, int PortNumber)
        {
            if (_IsRunning == false)
            {
                _HostName = HostName;
                _PortNumber = PortNumber;
                if (_IsServer)
                {
                    IPAddress ip = Dns.GetHostEntry(Environment.MachineName).AddressList[0];
                    _Server = new TcpListener(ip, _PortNumber);
                    _ServerThread = new Thread(new ThreadStart(this.serverProcess));
                    _ServerThread.Start();
                }
                else
                {
                    TcpClient tcpclient = new TcpClient(_HostName, _PortNumber);
                    createClientSocketJob(tcpclient);
                }
                _IsRunning = true;
            }
        }

        /// <summary>
        /// Сервер эсвэл клиент холболтыг унтраана
        /// </summary>
        public void Desconnect()
        {
            if (_Server != null)
            {
                try { _Server.Stop(); }
                catch (Exception ex) { ex.ToString(); }
                _Server = null;
            }

            int l = _ClientList.Count;
            for (int i = 0; i < l; i++)
            {
                try
                {
                    (_ClientList[i] as ClientSocketJob).Stop();
                }
                catch { }
            }

            _ClientList.Clear();
            _ClientJobCount = 0;
            _IsRunning = false;

            if (_ServerThread != null)
            {
                try { _ServerThread.Abort(); }
                catch (Exception ex) { ex.ToString(); }
                _ServerThread = null;

                SocketCommandBlock cmd = new SocketCommandBlock();
                if (_IsServer)
                    cmd.DataAccess = SocketDataAccess.ServerStop;
                else
                    cmd.DataAccess = SocketDataAccess.ClientStop;

                MsgRecieved.DynamicInvoke(new object[] { null, cmd });
            }
        }

        /// <summary>
        /// Аль нэг холбоосыг таслана
        /// </summary>
        /// <param name="job"></param>
        public void RemoveJob(ClientSocketJob job)
        {
            try
            {
                _ClientList.Remove(job.JobIndex.ToString());
            }
            catch (Exception ex) { ex.ToString(); }
            if (_IsServer == false && _ClientList.Count == 0) _IsRunning = false;
        }

        /// <summary>
        /// Холболтыг чагнаж шинэ клиентийн холбоосыг бүртгэн авч цуглуулна
        /// </summary>
        private void serverProcess()
        {
            try
            {
                _Server.Start();

                SocketCommandBlock cmd = new SocketCommandBlock();
                cmd.DataAccess = SocketDataAccess.ServerStart;
                MsgRecieved.DynamicInvoke(new object[] { null, cmd });

                while (true)
                {
                    try
                    {
                        TcpClient tcpclient = _Server.AcceptTcpClient();

                        cmd.DataAccess = SocketDataAccess.Accept;
                        MsgRecieved.DynamicInvoke(new object[] { null, cmd });

                        if (_ClientDistinct)
                        {
                            var prevJob = existsClientSocketJobByIP(tcpclient);
                            if (prevJob != null)
                            {
                                prevJob.Stop();
                            }
                        }

                        createClientSocketJob(tcpclient);
                    }
                    catch (Exception ex)
                    {
                        ex.ToString();
                        this.Desconnect();
                    }
                    finally
                    {
                        Thread.Sleep(10);
                    }
                }
            }
            catch { }
        }

        /// <summary>
        /// Клиентийн хаяг давхардсан эсэхийг шалгах
        /// </summary>
        /// <param name="tcp"></param>
        /// <returns></returns>
        private ClientSocketJob existsClientSocketJobByIP(TcpClient tcp)
        {
            IPEndPoint ipep = (IPEndPoint)tcp.Client.RemoteEndPoint;
            string ip = ipep.Address.ToString();
            int l = _ClientList.Count;
            for (int i = 0; i < l; i++)
            {
                if ((_ClientList[i] as ClientSocketJob).IP == ip)
                {
                    return (_ClientList[i] as ClientSocketJob);
                }
            }
            return null;
        }

        /// <summary>
        /// Шинэ холбоос үүсгэж байна
        /// </summary>
        /// <param name="tcpclient"></param>
        private void createClientSocketJob(TcpClient tcpclient)
        {
            ClientSocketJob job = new ClientSocketJob(this, tcpclient, _ClientJobCount);
            _ClientList.Add(job.JobIndex.ToString(), job);
            _ClientJobCount++;

            job.Start();
        }
    }

    /// <summary>
    /// Клиент холбоос
    /// </summary>
    public class ClientSocketJob
    {
        private string _IP;
        public string IP
        {
            get { return _IP; }
            set { _IP = value; }
        }
        private long _JobIndex;
        public long JobIndex
        {
            get { return _JobIndex; }
        }
        private object _Tag;
        public object Tag
        {
            get { return _Tag; }
            set { _Tag = value; }
        }
        private object _Commit;
        public object Commit
        {
            get { return _Commit; }
            set { _Commit = value; }
        }

        private event SocketMessageHandler MsgRecieved;
        private event SocketHandler DataRecieved;
       
        private SocketLib _Main;
        private TcpClient _Client;
        public TcpClient Client
        {
            get { return _Client; }
            set { _Client = value; }
        }
        private Thread _ClientThread;

        /// <summary>
        /// Клиент холбоосын ажлын класс
        /// </summary>
        /// <param name="main">Үндсэн класс</param>
        /// <param name="tcpclient">Сокет клиент</param>
        /// <param name="jobindex">Дугаар</param>
        public ClientSocketJob(SocketLib main, TcpClient tcpclient, long jobindex)
        {
            IPEndPoint endp = (IPEndPoint)tcpclient.Client.RemoteEndPoint;
            _IP = endp.Address.ToString();
           
            _Main = main;
            _Client = tcpclient;
            _JobIndex = jobindex;

            DataRecieved += new SocketHandler(ClientSocketJob_DataRecieved);
            MsgRecieved += new SocketMessageHandler(ClientSocketJob_MsgRecieved);
        }

        void ClientSocketJob_MsgRecieved(ClientSocketJob sender, SocketCommandBlock msg)
        {
            _Main.CallMsgRecieved(sender, msg);
        }

        void ClientSocketJob_DataRecieved(ClientSocketJob sender, object data)
        {
            _Main.CallDataRecieved(sender, data);
        }

        /// <summary>
        /// Холбоосоор өгөгдөл илгээх
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public int DataSend(object data)
        {
            try
            {
                lock (_Client)
                {
                    byte[] bytes = ObjLib.Serialize(data);
                    int i = _Client.Client.Send(bytes);

                    SocketCommandBlock cmd = new SocketCommandBlock();
                    cmd.DataAccess = SocketDataAccess.Sent;
                    MsgRecieved.DynamicInvoke(new object[] { this, cmd });
                }
            }
            catch (Exception ex)
            {
                ex.ToString();
                this.Stop();
            }
            return 0;
        }

        /// <summary>
        /// Холбоос таслах
        /// </summary>
        /// <param name="exception"></param>
        public void Stop(Exception exception = null)
        {
            if (_Client != null)
            {
                try { _Client.Client.Close(); }
                catch (Exception ex) { ex.ToString(); }
                _Client = null;
            }

            _Main.RemoveJob(this);

            if (_ClientThread != null)
            {
                try { _ClientThread.Abort(); }
                catch (Exception ex) { ex.ToString(); }
                _ClientThread = null;

                SocketCommandBlock cmdClientStop = new SocketCommandBlock();
                cmdClientStop.DataAccess = SocketDataAccess.ClientStop;
                MsgRecieved.DynamicInvoke(new object[] { this, cmdClientStop });
            }
        }

        /// <summary>
        /// Холбоосын ажиллагааг эхлүүлэх
        /// </summary>
        public void Start()
        {
            if (_ClientThread == null && _Client != null)
            {
                _ClientThread = new Thread(new ThreadStart(clientProcess));
                _ClientThread.Start();
            }
        }

        /// <summary>
        /// Клиент холбоосоор дамжих өгөгдлийг хүлээн авна
        /// </summary>
        private void clientProcess()
        {
            try
            {
                SocketCommandBlock cmdClientStart = new SocketCommandBlock();
                cmdClientStart.DataAccess = SocketDataAccess.ClientStart;
                MsgRecieved.DynamicInvoke(new object[] { this, cmdClientStart });

                while (true)
                {
                    try
                    {
                        MemoryStream ms = new MemoryStream();
                        byte[] recb = new byte[_Client.Client.ReceiveBufferSize];
                        int reci = 0;

                        reci = _Client.Client.Receive(recb);
                        ms.Write(recb, 0, reci);
                        while (_Client.GetStream().DataAvailable)
                        {
                            reci = _Client.Client.Receive(recb);
                            ms.Write(recb, 0, reci);
                        }

                        byte[] bytes = (ms.Length == 0) ? (new byte[] { }) : ms.GetBuffer();
                        try { ms.Close(); }
                        catch { }
                        if (bytes == null || bytes.Length == 0) continue;

                        try
                        {
                            var obj = ObjLib.DeSerialize(bytes);
                            DataRecieved.Invoke(this, obj );
                        }
                        catch (Exception e)
                        {
                            e.ToString();
                        }
                        finally
                        {
                            SocketCommandBlock cmdReceive = new SocketCommandBlock();
                            cmdReceive.DataAccess = SocketDataAccess.Receive;
                            MsgRecieved.Invoke(this, cmdReceive);
                        }
                    }
                    catch (Exception ex)
                    {
                        ex.ToString();
                        this.Stop(ex);
                    }
                }
            }
            catch { }
        }

        public override string ToString()
        {
            return string.Format("{0}. ({1})", _JobIndex, _IP);
        }
    }


}


in SERVER FORM

        SocketLib _ServerSocket;

        event SocketHandler sh;
        event SocketMessageHandler smh;

        public frmServerForm()
        {
            InitializeComponent();

            this.Text = " [ Сервер ] - Хувилбар " + Application.ProductVersion;

            sh += frmServerForm_sh;
            smh += frmServerForm_smh;
        }

        void frmServerForm_smh(ClientSocketJob sender, SocketCommandBlock msg)
        {
            if (msg.DataAccess == SocketDataAccess.ClientStart)
            {
                lstConnectedDevices.Items.Add(sender);
            }
            if (msg.DataAccess == SocketDataAccess.ClientStop)
            {
                lstConnectedDevices.Items.Remove(sender);
            }
            if (sender == null)
            {
                lstLog.Items.Insert(0, msg.DataAccess.ToString());
            }
            else
            {
                lstLog.Items.Insert(0, "IP: " + sender.IP + " , Job: " + sender.JobIndex.ToString() + " , Access: " + msg.DataAccess.ToString());
            }
        }

        void frmServerForm_sh(ClientSocketJob sender, object data)
        {
            if (data == null || !(data is string)) return;

            lstLog.Items.Insert(0, "IP: " + sender.IP + " , Job: " + sender.JobIndex.ToString() + " , Data: " + data);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
           
            _ServerSocket = new SocketLib(true, true);
            _ServerSocket.DataRecieved += _ServerSocket_DataRecieved;
            _ServerSocket.MsgRecieved += _ServerSocket_MsgRecieved;
            int Setting_SocketServerPort = 1986;
            _ServerSocket.Connect(Environment.MachineName, Setting_SocketServerPort);
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);

            if (_ServerSocket != null)
            {
                _ServerSocket.Stop();
            }
        }

        void _ServerSocket_MsgRecieved(ClientSocketJob sender, SocketCommandBlock msg)
        {
            this.Invoke(smh, new object[] { sender, msg });
        }

        void _ServerSocket_DataRecieved(ClientSocketJob sender, object data)
        {
            this.Invoke(sh, new object[] { sender, data });
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            string data = txtMessage.Text;
            ClientSocketJob job = (ClientSocketJob)lstConnectedDevices.SelectedItem;
            _ServerSocket.SendToClient(job, data);
        }


in CLIENT FORM


        SocketLib _ClientSocket;

        event SocketHandler sh;
        event SocketMessageHandler smh;

        public frmChat()
        {
            InitializeComponent();

            this.Text = Controller.Current.AboutDocument.DocumentElement.FirstChild.InnerText;

            sh += frmChatForm_sh;
            smh += frmChatForm_smh;
        }

        void frmChatForm_smh(ClientSocketJob sender, SocketCommandBlock msg)
        {
            if (sender == null)
            {
                txtLog.AppendText(msg.DataAccess.ToString());
            }
            else
            {
                txtLog.AppendText("IP: " + sender.IP +
                    " , Job: " + sender.JobIndex.ToString() +
                    " , Access: " + msg.DataAccess.ToString());
            }
            txtLog.AppendText("\r\n");
        }

        void frmChatForm_sh(ClientSocketJob sender, object data)
        {
            txtLog.AppendText("IP: " + sender.IP +
                " , Job: " + sender.JobIndex.ToString() +
                " , Data: " + data);
            txtLog.AppendText("\r\n");
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            _ClientSocket = new SocketLib(false, true);
            _ClientSocket.DataRecieved += _ClientSocket_DataRecieved;
            _ClientSocket.MsgRecieved += _ClientSocket_MsgRecieved;
            string Setting_SocketServerName = "127.0.0.1";
            int Setting_SocketServerPort = 1986;
            _ClientSocket.Connect(Setting_SocketServerName, Setting_SocketServerPort);
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);

            if (_ClientSocket != null)
            {
                _ClientSocket.Stop();
            }
        }

        void _ClientSocket_MsgRecieved(ClientSocketJob sender, SocketCommandBlock msg)
        {
            this.Invoke(smh, new object[] { sender, msg });
        }

        void _ClientSocket_DataRecieved(ClientSocketJob sender, object data)
        {
            this.Invoke(sh, new object[] { sender, data });
        }

        private void button1_Click(object sender, EventArgs e)
        {
            _ClientSocket.SendToServer(textBox1.Text);
        }

No comments: