zoukankan      html  css  js  c++  java
  • C# Socket 处理 拆包、粘包

    1、采用TCP自定义协议通讯,协议由02(byte) + json字符串(byte[]) +03(byte)组成。

    ------Socket_Client.cs 服务端
    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;

    namespace MyTcp
    {
        public class Socket_Client
        {
            //接收绑定事件
            public delegate void ReceiveDelegate(string json);
            public event ReceiveDelegate onReceiveHandler;
            //----------------------------------------------
            private Socket ClientSocket;
            private string _serverip = "";
            private int _port = 0;
            //----------------------------------------------
            public bool KeepAlive = true;
            public Socket_Client(string ServerIp, int Port)
            {
                _serverip = ServerIp;
                _port = Port;
            }
            private void KeepAliveCheck()
            {
                while(true)
                {
                    try
                    {
                        Console.WriteLine("keep alive");
                        if (ClientSocket != null)
                        {
                            ClientSocket.Send(new byte[] { });//发送空字符
                        }
                        Thread.Sleep(5000);
                       // Thread.Sleep(600000);//10分钟
                    }catch(Exception ex)
                    {
                        MyLog.Log.v(ex);
                        break;
                    }
                }
            }
            public void Connect()
            {
                try
                {
                    IPAddress ipAddr = IPAddress.Parse(_serverip);
                    IPEndPoint endPoint = new IPEndPoint(ipAddr, _port);
                    ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    ClientSocket.Connect(endPoint);  //与远程主机建立连接
                    Console.WriteLine("成功连接到{0}。", ClientSocket.RemoteEndPoint);

                    Thread recTh = new Thread(RecMsg);
                    recTh.IsBackground = true;
                    recTh.Start(ClientSocket);
                    //启动线程每隔10分钟检查连通性
                    Thread threadCheck = new Thread(KeepAliveCheck);
                    threadCheck.IsBackground = true;
                    threadCheck.Start();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("连接失败:" + ex.Message);
                    MyLog.Log.v(ex);
                }
            }
            private void RecMsg(object o)
            {
                Socket connSocket = o as Socket;
                while (true)
                {
                    try
                    {
                        List<byte> lstArr = new List<byte>();
                        byte[] buffer = new Byte[1024];
                        int len = 0;
                        while ((len = connSocket.Receive(buffer)) > 0)
                        {
                            for (int i = 0; i < len; i++)
                            {
                                lstArr.Add(buffer[i]);
                            }
                            //处理粘包/拆包数据
                            lstArr = getRemaining(lstArr);
                        }
                    }
                    catch (Exception ex)
                    { //异常终止接收数据
                        MyLog.Log.v(ex);
                        throw ex;//抛出异常并退出线程
                    }
                }
            }
            private List<byte> getRemaining(List<byte> lstArr)
            {
                if (lstArr.Count == 0)
                    return lstArr;
                List<byte> newbyte = new List<byte>();
                int _lasindex = 0;
                for (int i = 0; i < lstArr.Count; i++)
                {
                    if (lstArr[i] == 3 && i > 0 && lstArr[i - 1] == 125)
                    {////结束字符 ascii码 "}"对应125
                        _lasindex = i;
                        break;
                    }
                }
                if (_lasindex == 0)
                    return lstArr;
                string _str = "";
                //截取字符串
                for (int i = 0; i < lstArr.Count; i++)
                {
                    if (lstArr[i] == 2 && lstArr.Count > (i + 1) && lstArr[i + 1] == 123)
                    {//ascii码 "{"对应123
                        //  _str = System.Text.Encoding.UTF8.GetString(lstArr.GetRange(i, _lasindex - i + 1).ToArray());
                        _str = System.Text.Encoding.UTF8.GetString(lstArr.GetRange(i + 1, _lasindex - i - 1).ToArray());  //去掉02 和03
                        break;
                    }
                }
                if ((lstArr.Count - _lasindex - 1) > 0)
                {
                    newbyte.AddRange(lstArr.GetRange(_lasindex + 1, lstArr.Count - _lasindex - 1));
                }
                //处理数据
              //  Console.WriteLine(_str);
                if (onReceiveHandler != null)
                {
                    onReceiveHandler(_str);
                }
                ////////////
                return getRemaining(newbyte);
            }
            /// <summary>
            /// 发送消息
            /// </summary>
            /// <param name="mess"></param>
            public void Send(string json)
            {
                try
                {
                    Thread sendTh = new Thread(SendMsg);
                    SendObj send = new SendObj();
                    send.socket = ClientSocket;
                    send.json = json;
                    sendTh.IsBackground = true;
                    sendTh.Start(send);
                }catch(Exception ex)
                {
                    MyLog.Log.v(ex);
                }
            }
            public void Close()
            {
                try
                {
                    if (ClientSocket != null)
                    {
                        ClientSocket.Close();
                    }
                }
                catch (Exception ex)
                {
                    MyLog.Log.v(ex);
                    throw ex;
                }
            }
            /********************************************************************/
            /// <summary>
            ///
            /// </summary>
            /// <param name="ob"></param>
            private void SendMsg(object ob)
            {
                try
                {
                    SendObj sendOb = ob as SendObj;
                    if (sendOb != null)
                    {
                        byte[] buffer = GetWrappedTextArray(sendOb.json);
                        Console.WriteLine(System.Text.Encoding.UTF8.GetString(buffer));
                        sendOb.socket.Send(buffer, buffer.Length, SocketFlags.None);
                    }
                }catch(Exception ex)
                {
                    MyLog.Log.v(ex);
                }
            }
            /// <summary>
            /// 0x02{}0x03
            /// </summary>
            /// <param name="text"></param>
            /// <returns></returns>
            private byte[] GetWrappedTextArray(string text)
            {
                byte[] oldbytes = Encoding.UTF8.GetBytes(text);
                byte[] newbytes = new byte[oldbytes.Length + 2];
                newbytes[0] = 2;
                oldbytes.CopyTo(newbytes, 1);
                newbytes[newbytes.Length - 1] = 3;
                return newbytes;
            }  
            private class SendObj
            {
               public Socket socket;
               public string json;
            }
        }
    }

    ---------Socket_Server.cs 客户端


    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;

    namespace MyTcp
    {
        public class Socket_Server
        { //接收绑定事件
            public delegate void ReceiveDelegate(string json);
            public event ReceiveDelegate onReceiveHandler;
            private Socket socketSrv;
            private string _serverip = "";
            private int _port = 0;
            static Dictionary<string, Socket> clientConnectionItems = new Dictionary<string, Socket> { };
            public Socket_Server(string ServerIp, int Port)
            {
                _serverip = ServerIp;
                _port = Port;
            }
            public void StartListen()
            {
                IPAddress ip = IPAddress.Parse(_serverip);
                IPEndPoint ipe = new IPEndPoint(ip, _port);
                socketSrv = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                try
                {
                    socketSrv.Bind(ipe);
                    socketSrv.Listen(10);
                    Console.WriteLine("等待连接……");
                    Thread mainTrd = new Thread(RunAccept);
                    mainTrd.IsBackground = true;
                    mainTrd.Start(socketSrv);
                }
                catch (Exception ex)
                {
                    MyLog.Log.v(ex);
                    Console.WriteLine(ex);
                }
            }
            private void RunAccept(object o)
            {
                Socket socket = o as Socket;
                while (true)
                {
                    try
                    {
                        Socket connection = socket.Accept();                     
                        string remoteEndPoint = connection.RemoteEndPoint.ToString();
                        Console.WriteLine("成功与" + remoteEndPoint + "客户端建立连接! ");
                        clientConnectionItems.Add(remoteEndPoint, connection);
                        Thread thread = new Thread(new ParameterizedThreadStart(recv));
                        thread.IsBackground = true;
                        thread.Start(connection);
                    }
                    catch (Exception ex)
                    {
                        MyLog.Log.v(ex);
                        Console.WriteLine(ex);
                        throw;
                    }
                }
            }
            /// <summary>
            /// 接收客户端发来的信息,客户端套接字对象
            /// </summary>
            /// <param name="socketclientpara"></param>    
            private void recv(object socketclientpara)
            {
                Socket socketServer = socketclientpara as Socket;
                int _FNW = 0;
                while (true)
                {
                    try
                    {
                        List<byte> lstArr = new List<byte>();
                        byte[] buffer = new Byte[1024];
                        int len = 0;
                        while ((len = socketServer.Receive(buffer)) > 0)
                        {
                            if (_FNW > 0)
                                _FNW = 0;
                            for (int i = 0; i < len; i++)
                            {
                                lstArr.Add(buffer[i]);
                            }
                            //处理粘包/拆包数据
                            lstArr = getRemaining(lstArr);
                        }
                        if(len==0)
                        {
                            _FNW++;
                            Thread.Sleep(5000);//15秒后断开连接
                            if (_FNW > 3)
                            {
                                //异常终止接收数据
                                MyLog.Log.v(socketServer.RemoteEndPoint + "远程连接关闭");
                                clientConnectionItems.Remove(socketServer.RemoteEndPoint.ToString());
                                Console.WriteLine("Client Count:" + clientConnectionItems.Count);
                                //提示套接字监听异常  
                                Console.WriteLine("客户端" + socketServer.RemoteEndPoint + "已经中断连接");
                                socketServer.Close();
                                socketServer.Dispose();
                                break;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        //异常终止接收数据
                        MyLog.Log.v(ex);
                        clientConnectionItems.Remove(socketServer.RemoteEndPoint.ToString());
                        Console.WriteLine("Client Count:" + clientConnectionItems.Count);
                        //提示套接字监听异常  
                        Console.WriteLine("客户端" + socketServer.RemoteEndPoint + "已经中断连接" + " " + ex.Message + " " + ex.StackTrace + " ");
                        socketServer.Close();
                        socketServer.Dispose();
                        break;
                    }
                }
            }

            private List<byte> getRemaining(List<byte> lstArr)
            {
                if (lstArr.Count == 0)
                    return lstArr;
                List<byte> newbyte = new List<byte>();
                int _lasindex = 0;
                for (int i = 0; i < lstArr.Count; i++)
                {
                    if (lstArr[i] == 3 && i > 0 && lstArr[i - 1] == 125)
                    {////结束字符 //125      0x7D      }
                        _lasindex = i;
                        break;
                    }
                }
                if (_lasindex == 0)
                    return lstArr;
                string _str = "";
                //截取字符串
                for (int i = 0; i < lstArr.Count; i++)
                {
                    if (lstArr[i] == 2 && lstArr.Count > (i + 1) && lstArr[i + 1] == 123)
                    {
                        //_str = System.Text.Encoding.UTF8.GetString(lstArr.GetRange(i, _lasindex - i + 1).ToArray());
                        _str = System.Text.Encoding.UTF8.GetString(lstArr.GetRange(i+1, _lasindex - i-1).ToArray());  //去掉02 和03
                        break;
                    }
                }
                if ((lstArr.Count - _lasindex - 1) > 0)
                {
                    newbyte.AddRange(lstArr.GetRange(_lasindex + 1, lstArr.Count - _lasindex - 1));
                }
                //处理数据
                //  Console.WriteLine(_str);
                if (onReceiveHandler != null)
                {
                    onReceiveHandler(_str);
                }
                ////////////
                return getRemaining(newbyte);
            }
            public void Send(string json)
            {
                try
                {
                    if (clientConnectionItems != null && clientConnectionItems.Count > 0)
                    {
                        Thread sendTh = new Thread(SendMsg);
                        sendTh.IsBackground = true;
                        sendTh.Start(json);
                    }
                }
                catch (Exception ex)
                {
                    MyLog.Log.v(ex);
                }
            }

            public void Close()
            {
                try
                {
                    if(clientConnectionItems!=null&& clientConnectionItems.Count>0)
                    {
                        foreach (var item in clientConnectionItems)
                        {
                            try
                            {
                                item.Value.Close();
                                item.Value.Dispose();
                            }catch(Exception ex)
                            {
                                Console.WriteLine("关闭连接"+item.Key+"出错:"+ex);
                                MyLog.Log.v("关闭连接"+item.Key+"出错:"+ex.Message);
                            }
                        }
                    }
                    if (socketSrv != null)
                    {
                        socketSrv.Close();
                        socketSrv.Dispose();
                    }
                }
                catch (Exception ex)
                {
                    MyLog.Log.v(ex);
                    Console.WriteLine(ex);
                    throw ex;
                }
            }
            /********************************************************************/
            /// <summary>
            ///
            /// </summary>
            /// <param name="ob"></param>
            private void SendMsg(object ob)
            {
                try
                {
                    String _sendMess = Convert.ToString(ob) ?? "";
                    byte[] buffer = GetWrappedTextArray(_sendMess);
                    Console.WriteLine(System.Text.Encoding.UTF8.GetString(buffer));
                    foreach (var item in clientConnectionItems)
                    {
                        try
                        {   
                            item.Value.Send(buffer, buffer.Length, SocketFlags.None);
                        }
                        catch(Exception ex)
                        {
                            MyLog.Log.v(ex);
                        }
                    }
                }
                catch (Exception ex)
                {
                    MyLog.Log.v(ex);
                }
            }
            /// <summary>
            /// 0x02{}0x03
            /// </summary>
            /// <param name="text"></param>
            /// <returns></returns>
            private byte[] GetWrappedTextArray(string text)
            {
                byte[] oldbytes = Encoding.UTF8.GetBytes(text);
                byte[] newbytes = new byte[oldbytes.Length + 2];
                newbytes[0] = 2;
                oldbytes.CopyTo(newbytes, 1);
                newbytes[newbytes.Length - 1] = 3;
                return newbytes;
            }
        }
    }
    ----------------------------------------------------------测试调用--------------------------------------------------------------------------

     1、启动客户端服务
        Socket_Client client = new Socket_Client("127.0.0.1", 20001);
        client.Connect();//连接
        client.onReceiveHandler += Client_onReceiveHandler;//接收消息
    2、启动服务端 
        Socket_Server ss = new Socket_Server("127.0.0.1", 20001);
        ss.StartListen();//启动监听
        ss.onReceiveHandler += Ss_onReceiveHandler;//接收消息
        

     

  • 相关阅读:
    Best Time to Buy and Sell Stock III <leetcode>
    Best Time to Buy and Sell Stock <leetcode>
    Search a 2D Matrix <leetcode>
    Minimum Path Sum <leetcode>
    Container With Most Water <leetcode>
    Binary Tree Level Order Traversal II <leetcode>
    Rotate Image <leetcode>
    获取安装的apk应用信息
    判断wifi连接是否可用
    kubectl常用命令汇总
  • 原文地址:https://www.cnblogs.com/pzxnet/p/12857663.html
Copyright © 2011-2022 走看看