Unity客户端长度信息法解决Socket粘包问题

游戏研发 专栏收录该内容
9 篇文章 1 订阅

客户端源代码:

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

public class Echo : MonoBehaviour
{
    //定义套接字
    Socket socket;
    //UGUI
    public InputField Input;
    public Text text;
    //缓冲区
    byte[] readbuff=new byte[1024];
    //缓冲区数据长度
    int buffCount=0;
    string recStr="";

    //异步连接
    public void Connection()
    {
        socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
        socket.BeginConnect("127.0.0.1",8888,connectCallback,socket);
    }

    //连接回调
    public void connectCallback(IAsyncResult ar)
    {
        try
        {
            Socket socket=(Socket) ar.AsyncState;
            socket.EndConnect(ar);
            Debug.Log("connect succed");
        }
        catch(SocketException e)
        {
            Debug.Log("socket fail"+e.ToString());
        }
        socket.BeginReceive(readbuff,buffCount,1024-buffCount,0,receivecallback,socket);
    }

    //接收回调
    public void receivecallback(IAsyncResult ar)
    {
        try
        {
             Socket socket=(Socket) ar.AsyncState;
             int count=socket.EndReceive(ar);
             buffCount+=count;
             //处理二进制消息
             OnReceiveData();
             string s=System.Text.Encoding.Default.GetString(readbuff,0,count);
             recStr=s+"\n"+recStr;
             socket.BeginReceive(readbuff,buffCount,1024-buffCount,0,receivecallback,socket);
        }
        catch(SocketException e)
        {
            Debug.Log("socket receive fail"+e.ToString());
        }
    }

    //异步发送
    public void Send()
    {
        string sendStr=Input.text;
        byte[] bodyBytes=System.Text.Encoding.Default.GetBytes(sendStr);
        Int16 len=(Int16)bodyBytes.Length;
        byte[] lenBytes=BitConverter.GetBytes(len);
        byte[] sendbytes=lenBytes.Concat(bodyBytes).ToArray();
        socket.BeginSend(sendbytes,0,sendbytes.Length,0,sendcallback,socket);
    }

    //发送回调
    private void sendcallback(IAsyncResult ar)
    {
        try
        {
            Socket socket=(Socket) ar.AsyncState;
            int count=socket.EndSend(ar);
            Debug.Log("Socket send succ ,number is:"+count);
        }
        catch(SocketException e)
        {
            Debug.Log("socket send erro:"+e.ToString());
        }
    }

    //更新UGUI界面的文本框
    public void Update() 
    {
        text.text=recStr;
    }

    //接收数据处理
    public void OnReceiveData()
    {
        Debug.Log("[Recv 1] buffercount="+buffCount);  //接收的总字节数(含长度)
        Debug.Log("[Recv 2] readbuffer="+BitConverter.ToString(readbuff));  //显示接收的数据的内容
        //消息长度小于2,不做处理
        if(buffCount<=2)
        {
            return;
        }
        Int16 bodyLength=BitConverter.ToInt16(readbuff,0);  //消息体长度
        Debug.Log("[Recv 3] bodylength="+bodyLength);   //显示消息体长度
        //消息长度大于2,但是不足长度,不做处理
        if(buffCount<2+bodyLength)
        {
            return;
        }
        string s=System.Text.Encoding.UTF8.GetString(readbuff,2,bodyLength);  //处理消息
        Debug.Log("[Recv 4] s="+s);   //显示消息内容
        //更新缓冲区
        int start=2+bodyLength;    //更新起始位置
        int count=buffCount-start;     //更新计数
        Array.Copy(readbuff,start,readbuff,0,count);     //缓冲区移位
        buffCount-=start;
        Debug.Log("[Recv 5] buffCount="+buffCount);   //显示计数
        recStr=s+"\n"+recStr;
        //继续读消息
        OnReceiveData();
    }
}

 

  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

打赏
文章很值,打赏犒劳作者一下
相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页

打赏

qq_15029743

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值