Socket粘包解包

服务端 

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

namespace Server007
{
    internal class NetManager : Singleton<NetManager>
    {
        Socket socket;
        public List<Client> clients = new List<Client>();
        public void Init()
        {
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socket.Bind(new IPEndPoint(IPAddress.Any, 8888));
            socket.Listen(10);
            socket.BeginAccept(AsyAcc, null);
        }

        private void AsyAcc(IAsyncResult ar)
        {

            Socket client = socket.EndAccept(ar);
            IPEndPoint ip = client.RemoteEndPoint as IPEndPoint;
            Client cli = new Client();
            cli.socket = client;
            //clients.Add(cli);

            Console.WriteLine("用户" + ip.Port.ToString() + "连接成功");

            cli.socket.BeginReceive(cli.data, 0, cli.data.Length, SocketFlags.None, AsyOnReceive, cli);

            socket.BeginAccept(AsyAcc, null);
        }

        private void AsyOnReceive(IAsyncResult ar)
        {
            Client cli = ar.AsyncState as Client;
            int len = cli.socket.EndReceive(ar);
            if (len <= 0)
            {
                cli.socket.Shutdown(SocketShutdown.Both);
                cli.socket.Close();
                clients.Remove(cli);
                return;
            }


            byte[] ndata = cli.data.Take(len).ToArray();
            //  收到的消息拼入流
            cli.sream = cli.sream.Concat(ndata).ToArray();
            while (cli.sream.Length >= 2)
            {
                //取出第一个包的长度
                short onelen = BitConverter.ToInt16(cli.sream, 0);
                if (cli.sream.Length >= 2 + onelen)
                {
                    //取出id
                    int id = BitConverter.ToInt32(cli.sream, 2);
                    //len是多个包的长度
                    //包身长度=one-4
                    //包身要去掉长度的2和id长度4之后再截取包身
                    byte[] data = cli.sream.Skip(6).Take(onelen - 4).ToArray();
                    //赋值
                    MsaData msaData = new MsaData();
                    msaData.data = data;
                    msaData.client = cli;
                    MessageCenter<MsaData>.Instance.Broadcast(id, msaData);
                    cli.sream = cli.sream.Skip(2 + onelen).ToArray();
                }
                else
                {
                    break;
                }
            }

            //byte[] rdata = new byte[len];
            //Buffer.BlockCopy(cli.data, 0, rdata, 0, len);

            //while (rdata.Length > 4)
            //{
            //    int bodylen = BitConverter.ToInt32(rdata, 0);
            //    byte[] body = new byte[bodylen];
            //    Buffer.BlockCopy(rdata, 4, body, 0, bodylen);

            //    byte[] infodata = new byte[bodylen - 4];
            //    Buffer.BlockCopy(body, 4, infodata, 0, bodylen - 4);
            //    int id = BitConverter.ToInt32(body, 0);

            //    MsaData msgData = new MsaData();
            //    msgData.client = cli;
            //    msgData.data = infodata;

            //    MessageCenter<MsaData>.Instance.Broadcast(id, msgData);

            //    int sylen = rdata.Length - 4 - bodylen;
            //    byte[] data = new byte[sylen];
            //    Buffer.BlockCopy(rdata, 4 + bodylen, data, 0, sylen);
            //    rdata = data;
            //}

            cli.socket.BeginReceive(cli.data, 0, cli.data.Length, SocketFlags.None, AsyOnReceive, cli);
        }

        public void OnSend(int id, byte[] body, Client client)
        {
            int bodylen = 4 + body.Length;
            byte[] endata = new byte[0];
            endata = endata.Concat(BitConverter.GetBytes((short)bodylen)).Concat(BitConverter.GetBytes(id)).Concat(body).ToArray();
            client.socket.BeginSend(endata, 0, endata.Length, SocketFlags.None, AsyOnSned, client);
        }

        private void AsyOnSned(IAsyncResult ar)
        {
            Client client = ar.AsyncState as Client;
            int len = client.socket.EndSend(ar);
        }
    }
}

unity客户端

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using UnityEngine;

public class NetManager : Singletion<NetManager>
{
    Socket socket;
    byte[] data = new byte[1024];
    byte[] stream = new byte[0];
    Queue<byte[]> que = new Queue<byte[]>();

    public void Init()
    {
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        socket.BeginConnect("127.0.0.1", 8888, AsyCon, null);
    }

    private void AsyCon(IAsyncResult ar)
    {
        socket.EndConnect(ar);
        Debug.Log("连接成功");
        socket.BeginReceive(data, 0, data.Length, SocketFlags.None, AsyRececive, null);
    }

    private void AsyRececive(IAsyncResult ar)
    {
        int len = socket.EndReceive(ar);
        if (len <= 0)
        {
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
            return;
        }
        //获取消息
        byte[] body = data.Take(len).ToArray();
        //拼接消息
        stream = stream.Concat(body).ToArray();
        while (stream.Length >= 2)
        {
            //取出第一个包长度
            short datalen = BitConverter.ToInt16(stream, 0);
            if (stream .Length>= 2+ datalen)
            {
                byte[]bodylen=stream.Skip(2).Take(datalen).ToArray();
                que.Enqueue(bodylen);//进队
                stream = stream.Skip(2 + datalen).ToArray();
            }
        }
        真实数据
        //byte[] rdata = new byte[len];
        //Buffer.BlockCopy(data, 0, rdata, 0, len);
        //while (rdata.Length > 4)
        //{
        //    //取出包头内容,就是包身的长度
        //    int body = BitConverter.ToInt32(rdata, 0);
        //    //包身内容开辟
        //    byte[] bodylen = new byte[body];
        //    Buffer.BlockCopy(rdata, 4, bodylen, 0, body);
        //    //进队
        //    que.Enqueue(bodylen);

        //    int sylen = rdata.Length - 4 - body;
        //    byte[] sydata = new byte[sylen];
        //    Buffer.BlockCopy(rdata, 4 + body, sydata, 0, sylen);
        //    rdata = sydata;
        //}

        socket.BeginReceive(data, 0, data.Length, SocketFlags.None, AsyRececive, null);
    }

    public void OnSend(int id, byte[] data)
    {
        int bodylen = 4 + data.Length;
        byte[] endata = new byte[0];
        endata = endata.Concat(BitConverter.GetBytes((short)bodylen)).Concat(BitConverter.GetBytes(id)).Concat(data).ToArray();


        //byte[] head = BitConverter.GetBytes(id);
        //byte[] body = head.Concat(data).ToArray();
        socket.BeginSend(endata, 0, endata.Length, SocketFlags.None, AsySend, null);
    }

    private void AsySend(IAsyncResult ar)
    {
        int len = socket.EndSend(ar);
    }

    public void UpDate()
    {
        while (que.Count > 0)
        {
            byte[] body = que.Dequeue();
            int id = BitConverter.ToInt32(body, 0);
            byte[] buffer = body.Skip(4).ToArray();
            MessageCenter<byte[]>.Instance.Broadcast(id, buffer);
           
        }
    }
}

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值