unity TPC异步连接(含粘包分包处理)

最近公司需要用unity里的项目与某硬件相连,写了一个简单的通信功能,不足之处望不吝赐教!

int BUFFER_SIZE=51200;    //定义接受Buffer长度
public Socket clientSocket;    //存储客户端实例
public Socket serverSocket;    //服务端实例
public Queue recQueue;    //接受信息队列
byte[] receiveBuffer=new byte[51200];    //创建一块缓冲
public List<Socket> clientSocketList=new List<Socket>();    //存储所有连接客户端对象(未做标识处理)
byte[] cacheBuffer=null;    //保存一条完整数据

//开启异步监听
public void BeginSocket(int port)
{
    string ip="";
    IPHostEntry ipEntry=Dns.GetHostEntry(Dns.GetHostName());
    foreach(IPAddress _ip in ipEntry.AddressList)
        {
            if(_ip.AddressFamily==AddressFamily.InterNetwork)
            {
                ip=_ip.ToString();    //获取本地IP
            }
        }
    IPEndPoint ipendpoint=new IPEndPoint(IPAddress.Parse(ip),port);    //定义节点
    serverSocket =new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocoType.Tcp);
    serverSocket.Bind(ipendpoint);    //绑定节点
    serverSocket.Listen(20);    //开启监听队列
    serverSocket.BeginAccept(AcceptCallback,serverSocket);    //开启异步监听回调
}
//连接客户端回调函数
public void AcceptCallback(IAsyncResult re)
{
    Socket ser=re.AsyncState as Socket;
    try
    {
        CliSocket=ser.EndAccept(re);        //结束accept接受客户端clientsocket
        clientSocketList.Add(CliSocket);    //将客户端socket存到链表
        cliSocket.BeginReceive(receiveBuffer,0,receiveBuffer.Length,SocketFlags.None,ReceiveCallBack,cliSocket);    //开启接受信息回调函数
        ser.BeginAccept(AcceptCallbacck,ser);    //再次开启回调        
    }
    catch(SocketException se)
    {
        Debug.Log(se.Message);
    }
    catch(Exception ce)
    {
        Debug.Log(ce);
        throw;
    }
}
//接受信息回调函数
public void ReceiceCallBack(IAsyncResult re)
{
    Socket socketClient=null;
    try
    {
        socketClient=re.IAsyncState as Socket;    
        clientSocket=socketClient;
        int receiveLen=clientsocket.EndReceive(re);    //接受客户端发送信息,返回值为字节数据长度
        if(receiveLen<=0)    //接受<=0字节,客户端请求断开服务端
        {
            Debug.Log("客户端已正常断开");
            socketClient.Close();
            return;
        }
        //缓存为空则新建字节数组    (此处处理粘包分包问题)
        if(cacheBuffer==null)
        {
            cacheBuffer=new Byte[receiveLen];    
            Array.Copy(receiveBuffer,cacheBuffer,receiveLen);    //将缓冲区内容复制给cache字节数组
        }
        else
        {
            //缓存不为空,进行拼接
            byte[] t=new byte[cacheBuffer.Length+receiveLen];
            Array.Copy(cacheBuffer,t,cacheBuffer.Length);
            Array.Copy(receiveBuffer,0,t,cacheBuffer.Length,receiveLen);
            cacheBuffer=t;    //此处将cache字节数组内容与缓冲区字节数组进行拼接
        }
        //数据长度小于等于一个int字节长度则继续接受
        if(cacheBuffer.Length<=4)
        {
            socketClient.BeginReceive(receiveBuffer,0,receiveBuffer.Length,SocketFlags.None,ReceiveCallBack,socketClient);    //继续接受缓冲数据
            return;
        }
        int msg=BitConverter.ToInt32(cacheBUffer,0);    //取出包头数据
        while(cacheBuffer!=null&&msgl+4<=cacheBuffer.Length)    //判断缓存包内至少含有一个完整的数据
        {
            byte[] msgbyte=new byte[msg];
            Array.Copy(cacheBuffer,msgbyte,msg);
            //拿到完整数据执行操作
            recQueue.Enqueue(msgbyte);    //将一条完整数据放入队列中
            if(msg+4==cacheBuffer.Length)    //包头数据正好与缓存包大小一致,再无粘包分包
            {
                cacheBuffer=null;    //将chache数组归为null
            }
            else
            {
                //缓存cacheBuffer中仍有数据
                byte[] tmpbyte=new byte[cacheBuffer.Length-msg-4];
                Array.Copy(cacheBuffer,msg+4,tmpbyte,0,cacheBuffer.Length-msg-4);
                cacheBuffer=tmpbyte;    //chache数组保留取出一整条数据后剩下的数据
            }
        }
     socketClent.BeginReceive(receiveBuffer,0,receiveBuffer.Length,SocketFlags.None,ReceiveCallBack,socketClient);   
    }
    catch(Exception ce){
        Debug.Log(ce.message);
        throw;
}
}

这是unity中通讯部分用到的几个主要接口,通过BeginSocket开启服务端监听模式,使用的异步通信方式,处理了粘包分包问题,只考虑了客户端正常断线(服务端接受0字节内容),暂时未考虑物理断线(发送心跳包)。

粘包分包处理的思想是首先对网络数据进行约束,--->(包头)int[包体长度]+(包体)byte[具体数据],缓冲区接受到信息后,使用一个cacheBuffer字节数组来进行判断,具体内容看上述代码,基本上可以满足粘包分包的问题。

猜你喜欢

转载自blog.csdn.net/qq_40097668/article/details/91359610
今日推荐