主要解决网络收发数据的问题
解决粘包问题的方法
- 长度信息法,在发送的信息之前附加上长度,比如发送两个字符串“hellounity”和love“”不希望单个被拆开,于是发送信息"10hellounity4love",尽当读取到的字符串的长度与表明的长度一致时,才会整体读取,否则就会等待数据完整到达。
- 固定长度法,每次都发送固定长度的字符,多余的空间用其他符号填充,如果字符串的长度大于固定长度,则拆分成小的字符,再拼接。
- 结束符号法,规定一个符号为结束符,那么可以区分不同的字符串。
实现采用长度信息法
长度信息法的代码
如果是16位的话,2个字节表示长度,如果是32位的话,4个字节表示长度,这里采用16位。
那么修改Send
函数,之前的Send
函数如下:
public void Send()
{
//Send
string sendStr = InputFeld.text;
byte[] sendBytes = System.Text.Encoding.Default.GetBytes(sendStr);
socket.Send(sendBytes);
修改之后的Send
函数如下,主要是附加了长度信息
public void Send()
{
//Send
string sendStr = InputFeld.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.Send(sendBytes);
}
比如HelloWorld
,修改之后成为0AHelloWorld
再转成二进制。
接收的时候需要一个buffCount
表示缓存区的以及读入的数据的长度,然后据此判断(16位):
buffCount <=2
,说明缓存区中还没有数据,不处理。- 缓存区数据无法构成完整的消息,不处理,等待下一次接收。
- 缓存区数据长度大于完整信息长度,取出字符串,并且更新缓冲区,目前采用后面数据直接覆盖前面数据的方法,类似于数组删除一个数据之后,后面的数据都往前移。
代码整合
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 InputFeld;
public Text text;
//接收缓冲区
byte[] readBuff = new byte[1024];
//接收缓冲区的数据长度
int buffCount = 0;
//显示文字
string recvStr = "";
//点击连接按钮
public void Connection()
{
//Socket
socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
//为了精简代码:使用同步Connect
// 不考虑抛出异常
socket.Connect("127.0.0.1", 8888);
socket.BeginReceive( readBuff, buffCount,
1024-buffCount, 0, ReceiveCallback, socket);
}
//Receive回调
public void ReceiveCallback(IAsyncResult ar){
try {
Socket socket = (Socket) ar.AsyncState;
//获取接收数据长度
int count = socket.EndReceive(ar);
buffCount += count;
//处理二进制消息
OnReceiveData();
//继续接收数据
socket.BeginReceive( readBuff, buffCount,
1024-buffCount, 0, ReceiveCallback, socket);
}
catch (SocketException ex){
Debug.Log("Socket Receive fail"