c# Socket通讯中关于粘包,半包的处理,加分割符

来源:互联网 发布:4g网络优化工程师工资 编辑:程序博客网 时间:2024/05/18 05:32
using System;using System.Collections.Generic;using System.Text;using System.Net.Sockets;using System.Threading;namespace EventBase{    /*解决Socket的粘包处理     使用方法        A2DTcpClient client = new A2DTcpClient("127.0.0.1", 5000);        client.NewMessageReceived += new MessageReceived(client_NewMessageReceived);        client.Connect();        client.Send("HELLO");        client.Close();        static void client_NewMessageReceived(string msg)        {            Console.WriteLine(msg);        }     */    public delegate void MessageReceived(string msg);    public class A2DTcpClient    {        public const string terminateString = "\r\n"; //消息的结尾标记        public const int receiveBufferSize = 1024; //缓冲区大小        private string RemoteServer { get; set; }        private int RemotePort { get; set; }        private TcpClient tcpClient;        public event MessageReceived NewMessageReceived;        public A2DTcpClient(string remoteServer, int remotePort)        {            this.RemotePort = remotePort;            this.RemoteServer = remoteServer;            tcpClient = new TcpClient();        }        public void Connect()        {            if (tcpClient.Connected)                throw new Exception("Connected, cannot re-connect.");            tcpClient.Connect(this.RemoteServer, this.RemotePort);            ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveMessage), tcpClient.Client);            Thread.Sleep(2000);//强制暂停,为了上面的线程运行        }        public void Close()        {            if (!tcpClient.Connected)                throw new Exception("Closed, cannot re-close.");            tcpClient.Close();        }        StringBuilder sb = new StringBuilder(); //这个是用来保存:接收到了的,但是还没有结束的消息        public void ReceiveMessage(object state) //这个函数会被以线程方式运行        {            Socket socket = (Socket)state;            while (true)            {                byte[] buffer = new byte[receiveBufferSize]; //buffer大小,此处为1024                int receivedSize = socket.Receive(buffer);                string rawMsg = System.Text.Encoding.Default.GetString(buffer, 0, receivedSize);                int rnFixLength = terminateString.Length; //这个是指消息结束符的长度,此处为\r\n                for (int i = 0; i < rawMsg.Length; ) //遍历接收到的整个buffer文本                {                    if (i <= rawMsg.Length - rnFixLength)                    {                        if (rawMsg.Substring(i, rnFixLength) != terminateString) //非消息结束符,则加入sb                        {                            sb.Append(rawMsg[i]);                            i++;                        }                        else                        {                            this.OnNewMessageReceived(sb.ToString()); //找到了消息结束符,触发消息接收完成事件                            sb.Clear();                            i += rnFixLength;                        }                    }                    else                    {                        sb.Append(rawMsg[i]);                        i++;                    }                }            }        }        private void OnNewMessageReceived(string msg)        {            if (this.NewMessageReceived != null)                this.NewMessageReceived.Invoke(msg);        }        public void Send(string str)        {            if (!this.tcpClient.Connected)                throw new Exception("Closed, cannot send data.");            str += terminateString;            byte[] byteArray = System.Text.Encoding.Default.GetBytes(str);            this.tcpClient.Client.Send(byteArray);        }    }}

0 0