C# TCP通信


服務端代碼,包含遠程客戶端類、服務端類、UI。
//遠程客戶端類
class RemoteClient { public TcpClient client{get; private set;} public BinaryReader br{get; private set;} public BinaryWriter bw{get; private set;} public string userName {get; set; } public RemoteClient(TcpClient client) { this.client = client; NetworkStream networkStream = client.GetStream(); br = new BinaryReader(networkStream); bw = new BinaryWriter(networkStream); this.userName = (client.Client.RemoteEndPoint as IPEndPoint).Address.ToString() + ":"+(client.Client.RemoteEndPoint as IPEndPoint).Port.ToString(); } public void Close() { br.Close(); bw.Close(); client.Close(); } }
    /// <summary>
    /// 服務器的類
    /// </summary>
    class _TcpServer
    {
        //遠程客戶端對象集合
        List<RemoteClient> remoteClientList = new List<RemoteClient>();     
        private TcpListener tcpServer;

        public _TcpServer(string localIP,int port)
        {
            /// <summary>使用的本機IP地址</summary>
            IPAddress localAddress = IPAddress.Parse(localIP); 
            tcpServer = new TcpListener(localAddress, port);
            tcpServer.Start();
            //創建一個線程監聽客戶端連接請求
            Thread myThread = new Thread(ListenClientConnect);
            myThread.Start();
        }

        /// <summary>接收客戶端連接</summary>
        private void ListenClientConnect()
        {
            TcpClient newClient = null;
            while (true)
            {
                try
                {
                    newClient = tcpServer.AcceptTcpClient();
                }
                catch
                {
                    //當單擊“停止監聽”或者退出此窗體時AcceptTcpClient()會產生異常
                    //因此可以利用此異常退出循環
                    break;
                }
                //每接受一個客戶端連接,就創建一個對應的線程循環接收該客戶端發來的信息
                RemoteClient user = new RemoteClient(newClient);
                Thread threadReceive = new Thread(ReceiveData);
                threadReceive.Start(user);
                remoteClientList.Add(user);
                ClassVar.WriteLogCommon(Environment.NewLine + "有遠程主機連接到本機,遠程主機信息:"+user.userName);
            }
        }       

        /// <summary>
        /// 處理接收的客戶端數據
        /// </summary>
        /// <param name="userState">客戶端信息</param>
        private void ReceiveData(object userState)
        {
            RemoteClient user = userState as RemoteClient;
            TcpClient client = user.client;
            while (true)
            {
                byte[] BytesLenth = null;
                byte[] BytesContent = null;
                try
                {
                    if (user == null || user.br == null || user.client.Connected == false)
                    {
                        break;
                    }
                    BytesLenth = user.br.ReadBytes(2);
                    int lenth = BitConverter.ToInt16(BytesLenth, 0);
                    BytesContent = user.br.ReadBytes(lenth - 2);
                    string conContent = Encoding.Default.GetString(BytesContent);                 
                    //如果收到是心跳信息
                    if (conContent == "0000")
                    {
                        lock (ClassVar.frmMain.objTimeSpan)
                        {
                            ClassVar.frmMain.timeSpan = 0;                         
                        }
                        ClassVar.WriteLogCommonXT(Environment.NewLine + "收到心跳消息");
                    }
                    //如果是警情信息則加入到消息隊列
                    else
                    {
                        lock (ClassVar.frmMain.lockQue)
                        {
                            ClassVar.frmMain.queue119Xml.Enqueue(conContent);                            
                        }
                        ClassVar.WriteLogCommon(Environment.NewLine + "收到數據:" + conContent);
                    }
                }
                catch (Exception ex)
                {
                    RemoveUser(user);
                    ClassVar.WriteErrorLog("接收消息異常:" + Environment.NewLine + "ReceiveData" + ex.ToString());
                }
            }
        }

        /// <summary>移除用戶</summary>
        /// <param name="user">指定要刪除的用戶</param>
        private void RemoveUser(RemoteClient remoteClient)
        {
            remoteClientList.Remove(remoteClient);
            remoteClient.Close();          
        }
    }

服務端UI

        //服務器給本機發送的心跳計時鎖對象
        public object lockQue = new object();
//接收的客戶端消息列表
public Queue<string> queue119Xml = new Queue<string>();
        private void IniServer()
        {
            //啟動監聽119服務器,用於接收發送119發送的消息
            _TcpServer _119TcpListen = new _TcpServer(ClassVar.localIPAddr, 11118);
            Thread threadRead119 = new Thread(new ThreadStart(Read119QueThread));
            threadRead119.IsBackground = true;
            threadRead119.Start();
        }
       //讀取消息隊列
        private void Read119QueThread()
        {
            while (true)
            {
                try
                {
                    if (queue119Xml.Count > 0)
                    {
                        lock (lockQue)
                        {
                            string xml = queue119Xml.Dequeue();
                            F119ToLocal(xml);
                        }
                    }
                }
                catch (Exception ex)
                {
                    ClassVar.WriteErrorLog("方法Read119QueThread出錯,詳細信息:" + ex.ToString());
                }
                Thread.Sleep(5);
            }
        } 

 

    /// <summary>
    /// 客戶端類
    /// </summary>
    class _Client
    {
        // tcp通信對象
        private TcpClient tcpClient;
        // tcp通信中讀取數據的對象
        private BinaryReader br;
        // tcp通信中寫數據的對象
        private BinaryWriter bw;
        // 通信的遠程服務器ip
        private string IP;
        // 通信的遠程服務器端口
        private int port;

        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="ip">服務器IP</param>
        /// <param name="port">服務器開放的通信端口號</param>
        public _Client(string ip,int port)
        {
            this.IP = ip;
            this.port = port;
        }

        /// <summary>
        /// 連接服務器
        /// </summary>
        public void Connect()
        {
            try
            {
                tcpClient = new TcpClient(IP, port);
                //獲取網絡流
                NetworkStream networkStream = tcpClient.GetStream();
                //將網絡流作為二進制讀寫對象
                br = new BinaryReader(networkStream);
                bw = new BinaryWriter(networkStream);
            }
            catch (Exception ex)
            {
                ClassVar.WriteErrorLog("連接服務器出錯:" + Environment.NewLine + "Connect" + ex.ToString());
            }
            //后台心跳消息線程
            Thread threadHeart = new Thread(new ThreadStart(SendHeart));
            threadHeart.IsBackground = true;
            threadHeart.Start();
        }

        /// <summary>
        /// 重連
        /// </summary>
        public void Reconnect()
        {
            try
            {
                if (tcpClient!=null)
                {
                    tcpClient.Close();
                }              
                tcpClient = new TcpClient(IP, port);
                //獲取網絡流
                NetworkStream networkStream = tcpClient.GetStream();
                //將網絡流作為二進制讀寫對象
                br = new BinaryReader(networkStream);
                bw = new BinaryWriter(networkStream);
            }
            catch(Exception ex)
            {
                ClassVar.WriteErrorLog("重連服務器出錯:" + Environment.NewLine + "Reconnect" + ex.ToString());
            }
        }
      
        /// <summary>
        /// 給服務器心跳,10秒一次
        /// </summary>
        private void SendHeart()
        {
            while (true)
            {
                Thread.Sleep(10000);
                SendMsg("0000");
            }
        }
        
        /// <summary>
        /// 發送消息到服務器的方法,帶發送長度
        /// </summary>
        /// <param name="msg">消息內容</param>
        public void SendMsg(string msgs)
        {
            try
            {
                byte[] msg = Encoding.UTF8.GetBytes(msgs);
                int length = msg.Length;
                short lengthall = (short)(length + 2);
                byte[] lengthByte = System.BitConverter.GetBytes(lengthall);
                byte[] all = lengthByte.Concat(msg).ToArray();
                //然后將字節數組寫入網絡流
                if (bw != null && tcpClient.Connected==true)
                {
                        bw.Write(all);
                        bw.Flush();
                        if (msgs == "0000")//心跳寫單獨的文件
                        {
                            ClassVar.WriteLogCommonXT(Environment.NewLine + "成功發送數據:" + msgs);
                        }
                        else
                        {
                            ClassVar.WriteLogCommon(Environment.NewLine + "成功發送數據:" + msgs);
                        }
                }
                else
                {
                    this.Reconnect();
                }
            }
            catch (Exception ex)
            {
                ClassVar.WriteErrorLog("發送消息到服務器出錯:" + Environment.NewLine + "SendMsg" + ex.ToString());
            }
        }
    }

 客戶端代碼

        // 與服務器通信的類
        _Client client ;
        //服務器給本機發送的心跳計時鎖對象
        public object objTimeSpan = new object();
        //服務器給本機發送的心跳計時
        public int timeSpan = 0;
 private void IniClient()
        {
            client = new _Client(_119ServerIP, _119ServerPort);
            //連接服務器
            client.Connect();
            //與服務器重連判斷線程
            Thread threadChenck = new Thread(new ThreadStart(CheckHeart));
            threadChenck.IsBackground = true;
            threadChenck.Start();
            client.SendMsg("測試發送信息到服務端");
        }
        // 重連判斷
        private void CheckHeart()
        {
            while (true)
            {
                Thread.Sleep(3000);
                lock (objTimeSpan)
                {
                    timeSpan = timeSpan + 2;
                }
                if (timeSpan >= maxTime)
                {
                    client.Reconnect();
                    timeSpan = 0;
                }
            }
        }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM