全景图传输

全景图传输

三月 21, 2022

全景图

知识储备

将全景图转变为Byte数组

1
2
3
4
5
Camera.main.RenderToCubemap(cm);
texture2D = new Texture2D(width, hight);
texture2D.SetPixels(cm.GetPixels(CubemapFace.NegativeZ));
texture2D.Apply();
byt = texture2D.EncodeToPNG();

将Byte数组变成全景图

1
2
3
4
texture2DFix.LoadImage(byt);
texture2DFix.Apply
cm1.SetPixels(texture2DFix.GetPixels(), CubemapFace.PositiveZ);
cm1.Apply();

网络传输

名字设为 I P 地址名

1.发送连接信号并在服务器创建位置

图像处理

1
for (int i = 1; i < width + 1; i++) Array.Copy(cmmcolors, width * (width - i), ReCmmcolors, width * (i - 1), width);//上下翻转

协议处理

1
2
3
4
5
6
7
print(point.Right.Length);
string str = pos.x.ToString() + " " + pos.y.ToString() + " " + pos.z.ToString() + " " + "PX ";
byte[] bytstr= System.Text.Encoding.UTF8.GetBytes(str);//单独编译

byte[] sendByt = new byte[point.Right.Length+ bytstr.Length];
bytstr.CopyTo(sendByt, 0);
point.Right.CopyTo(sendByt, bytstr.Length);//合并编码
1
2
3
4
5
6
 Texture2D = new Texture2D(width, width);
byte[] image = sendByt.Skip(bytstr.Length).ToArray();//需要using System.Linq;//截取字节
print(image.Length);
// Array.Reverse(image);//可以使图像旋转180度
print(Texture2D.LoadImage(image));
Texture2D.Apply();5.4.1

获取本地 I P 地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public string GetLocalIp()
{
///获取本地的IP地址
string AddressIP = string.Empty;
foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
{

if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
{

AddressIP = _IPAddress.ToString();
}
}
return AddressIP;
}

基本网络架构

服务器端

Connection

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public CloudService() {
msgHandle = new MsgHandle();
}
public int NewIndex() {
if (conns == null) {
return -1;
}
for (int i = 0; i < conns.Length; i++) {
if (conns[i] == null) {
conns[i] = new Conn();
return i;
}
else if (conns[i].isUse == false) {
return i;
}
}
return -1;
}
public void ServiceStart(string host, int port) {
conns = new Conn[maxConn];
for (int i = 0; i < maxConn; i++) {
conns[i] = new Conn();
}
Listerfd = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipAdr = IPAddress.Parse(host);
IPEndPoint ipEp = new IPEndPoint(ipAdr, port);
Listerfd.Bind(ipEp);
Listerfd.Listen(maxConn);
Listerfd.BeginAccept(AcceptCb, null);
status = true;
NetCloudServerManager.instance.debug.text+=("\n"+"[服务器]启动成功");
}

Accept Cb 异步监听

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public void AcceptCb(IAsyncResult ar) {
Socket socket = Listerfd.EndAccept(ar);//要放在try外面
try {
//接收客户端
int index = NewIndex();
if (index < 0) {
socket.Close();
Debug.Log("[警告]连接已满");
}
else {
Conn conn = conns[index];
conn.Init(socket);
string host = conn.GetAdress();
Debug.Log("客户端连接:[" + host + "] conn池ID:" + index);
conn.socket.BeginReceive(conn.readBuff, conn.buffCount, conn.BuffRemain(), SocketFlags.None, ReciveCb, conn);//接收的同时调用ReciveCb回调函数
}
Listerfd.BeginAccept(AcceptCb, null);//再次调用AcceprCb回调函数
}
catch (Exception e) {
Debug.Log("AccpetCb 失败:" + e.Message);
}
}

出现莫名其妙的问题,等待异步需要放在 try 外面,不然会抛出 AcceptCb只能在主线程调用,要我放在awake和start中

Recive Cb异步接收

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public void ReciveCb(IAsyncResult ar) {
Conn conn = (Conn)ar.AsyncState;//这个AsyncState就是上面那个BeginRecive函数里面最后一个参数
lock (conn) {
try {
int count = conn.socket.EndReceive(ar);//返回接收的字节数
//没有信息就关闭
if (count <= 0) {
Debug.Log("收到[" + conn.GetAdress() + "] 断开连接");
conn.Close();
return;
}
conn.buffCount += count;
ProcessData(conn);

//继续接收
conn.socket.BeginReceive(conn.readBuff, conn.buffCount, conn.BuffRemain(), SocketFlags.None, ReciveCb, conn);
}
catch (Exception e) {
Debug.Log("Recive失败" + e.Message);
}
}
}
public void ProcessData(Conn conn) {
//小于字节长度
if (conn.buffCount < sizeof(Int32)) {
return;
}
Debug.Log("接收到了 " + conn.buffCount + " 个字节");
Array.Copy(conn.readBuff, conn.lenByte, sizeof(Int32));
conn.msgLength = BitConverter.ToInt32(conn.lenByte, 0);
//小于最小要求长度则返回表示未接收完全
if (conn.buffCount < conn.msgLength + sizeof(Int32)) {
return;
}


//这里接收信息有个细节,因为之前发送回来的信息又被加了一次长度,相当于要把他所有的信息接收完了
//才算接收成功,然后再把前面的sizeof(Int32)去掉,剩下的就是带长度的信息了
ProtocolByte proto = new ProtocolByte();
ProtocolByte protoStr = new ProtocolByte();
ProtocolByte protocol = proto.Decode(conn.readBuff, sizeof(Int32), conn.msgLength) as ProtocolByte;
protoStr.AddString(conn.GetAdress());
protocol.bytes = protoStr.bytes.Concat(protocol.bytes).ToArray();
lock(msgHandle.msgList) {
msgHandle.msgList.Add(protocol);
}
Debug.Log( protocol.GetDesc());


//清除已处理的消息
int count = conn.buffCount - conn.msgLength - sizeof(Int32);
Array.Copy(conn.readBuff, sizeof(Int32) + conn.msgLength, conn.readBuff, 0, count);
conn.buffCount = count;
//如果还有多余信息就继续处理
if (conn.buffCount > 0) {
ProcessData(conn);
}

Conn类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public class Conn 
{
public const int BUFFER_SIZE = 16384;
public Socket socket;
public bool isUse = false;
public byte[] readBuff = new byte[BUFFER_SIZE];
public int buffCount = 0;
public Int32 msgLength = 0;
public byte[] lenByte = new byte[sizeof(Int32)];

public ProtocolByte assistProtolByte;
public Conn() {
readBuff = new byte[BUFFER_SIZE];
assistProtolByte = new ProtocolByte();
}
public void Init(Socket socket) {
this.socket = socket;
isUse = true;
buffCount = 0;
}
public int BuffRemain() {
return BUFFER_SIZE - buffCount;
}
public string GetAdress() {
if (!isUse) { return "无法获取地址"; }
return socket.RemoteEndPoint.ToString();
}
public void Close() {
if (!isUse) {
return;
}
Console.WriteLine("[断开连接]" + GetAdress());
socket.Close();
isUse = false;
}

public bool SendMsg(ProtocolBase protol) {
string proName = protol.GetName(); ;
return SendMsg(protol, proName);

}
public bool SendMsg(ProtocolBase protol, string protolName) {

ProtocolByte protocolByte1 = new ProtocolByte();
protocolByte1.AddString(protolName);
byte[] protolNameByte = protocolByte1.bytes;
byte[] b = protol.Encode();
byte[] len1 = BitConverter.GetBytes(protolNameByte.Length + b.Length);
byte[] sendByte = len1.Concat(protolNameByte).Concat(b).ToArray();
socket.Send(sendByte);
Debug.Log("sendByte " + sendByte.Length);
Debug.Log("sendBytes " + GetDesc(sendByte));
return true;
}
public string GetDesc(byte[] bytes) {
string str = "";
if (bytes == null) return str;
for (int i = 0; i < bytes.Length; i++) {
int b = (int)bytes[i];
str += b.ToString() + " ";
}
return str;
}
}

消息处理类

区别于客户端消息类,处理消息时,需要在接收的消息中加入传来的消息IP地址防止找不到回溯玩家。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
public class MsgHandle 
{
public int num = NetCloudServerManager.instance.HandleMsgNum;
Dictionary<string, ProtocolBase> oneMessager = new Dictionary<string, ProtocolBase>();
public List<ProtocolBase> msgList = new List<ProtocolBase>();

ProtocolByte assistProtocol;


public void Running() {
while(msgList.Count>0&&num>0) {
num--;
//处理长度和将协议分开
assistProtocol = msgList[0] as ProtocolByte;
if(assistProtocol==null) {
Debug.Log("消息转化失败");
lock (msgList) {
msgList.RemoveAt(0);
}
return;
}
int start = 0;
string IpAddress = assistProtocol.GetString(start, ref start);
string protocolName=assistProtocol.GetString(start, ref start);
//int protocolNameLen=System.Text.Encoding.UTF8.GetBytes(protocolName).Length + sizeof(Int32);
switch (protocolName) {
case "ProtocolCubeTexture":
ProtocolCubeTexture protocolCubeTexture = new ProtocolCubeTexture();
ProtocolCubeTexture aprotocol = protocolCubeTexture.Decode(assistProtocol.bytes, start, assistProtocol.bytes.Length) as ProtocolCubeTexture;
if (aprotocol == null) break;
PointMessage point = new PointMessage();
point.ResolveToPointMessage(aprotocol.Coord, aprotocol.CubemapFace, aprotocol.srcTexture);
NetCloudServerManager.instance.PM.Add(point);
break;

case "Start":
StartProcessData(assistProtocol, start, IpAddress);

break;
}
lock(msgList) {
msgList.RemoveAt(0);
}
//ProtocolCubeTexture protocol = msgList[0] as ProtocolCubeTexture;

}
num = NetCloudServerManager.instance.HandleMsgNum;

}

private void StartProcessData(ProtocolByte protocol,int start,string SendIPAddress) {
ProtocolStr protocolStr = new ProtocolStr();
Debug.Log("start" + start + " lenth" + assistProtocol.bytes.Length);
ProtocolStr protocolstr = protocolStr.Decode(assistProtocol.bytes, start, assistProtocol.bytes.Length-start) as ProtocolStr;
NetCloudServerManager.instance.debug.text += ("\n" + protocolstr.str);
string[] CoordStrs = protocolstr.str.Split(',');
float[] Coord = new float[3];
for (int i = 0; i < 3; i++)
Coord[i] = float.Parse(CoordStrs[i]);
Camera camm = NetCloudServerManager.instance.cam;
camm.transform.position = new Vector3( Coord[0], Coord[1], Coord[2]);
PointMessage point = new PointMessage();

if ( camm.RenderToCubemap(point.cubemap)) {
int index = -1;
Conn[] conns = NetCloudServerManager.cs.conns;
for (int i = 0; i < conns.Length; i++) {
if (conns[i] == null)
continue;
if (!conns[i].isUse)
continue;
if(conns[i].GetAdress()==SendIPAddress) {
index = i;
}
//print(" 将消息传播" + conns[i].GetAdress());
}
if (index < 0)
return;
int width = NetCloudServerManager.instance.width;
ProtocolCubeTexture protocolCube = new ProtocolCubeTexture();
protocolCube.srcTexture = new Texture2D(width, width);
for (int i = 0; i < 3; i++)
protocolCube.Coord[i] = int.Parse(CoordStrs[i]);
for (int i=0;i<6;i++) {
protocolCube.CubemapFace = i;
protocolCube.srcTexture.SetPixels(point.cubemap.GetPixels((CubemapFace)i));
protocolCube.srcTexture.Apply();
conns[index].SendMsg(protocolCube);
}
}
else {
NetCloudServerManager.instance.debug.text+= ("\n" + protocolstr.str+"渲染失败");
}
}
}

PointMessage 点消息类

1
2
3
4
5
6
7
8
9
10
11
public class PointMessage {
public Vector3 pos;
public Cubemap cubemap;
static int width;
public PointMessage() {
pos = Vector3.zero;
width = NetCloudServerManager.instance.width;

cubemap = new Cubemap(width, TextureFormat.RGBA32, false);
}
}

客户端

Connect 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
public class Connect 
{
// Start is called before the first frame update
public static Socket socket;
int BUFFER_SIZE = NetCloudClientManager.instance.BUFFER_SIZE;
byte[] readBuff ;
private int buffCount = 0;

private Int32 msgLength = 0;
private byte[] lenByte = new byte[sizeof(Int32)];

public ProtocolByte assistProtolByte;

public MsgHandle msgHandle = new MsgHandle();

public enum Status {
None,Connect
};
public Status status = Status.None;
public static int width = 256;

public Connect() {
readBuff = new byte[BUFFER_SIZE];
assistProtolByte = new ProtocolByte();
}

public bool Connetion(string host, int port) {

//清理text
try {
//Socket
socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
if (host.Length == 0) {
host = "192.168.50.142";
port = 1234;
}

socket.Connect(host, port);
status = Status.Connect;
NetCloudClientManager.instance.debug.text += ("\n" + "客户端地址" + socket.LocalEndPoint.ToString());
socket.BeginReceive(readBuff, buffCount, BUFFER_SIZE - buffCount, SocketFlags.None, ReceiveCb, readBuff);
return true;
}
catch(Exception e) {
NetCloudClientManager.instance.debug.text += ("\n" + "客户端失败"+e.Message );
return false;

}
// clientText.text = "客户端地址" + socket.LocalEndPoint.ToString();
//Recv


}

private void ReceiveCb(IAsyncResult ar) {
try {
//count是接收数据的大小
int count = socket.EndReceive(ar);
buffCount += count;
ProcessData();
socket.BeginReceive(readBuff,buffCount , BUFFER_SIZE-buffCount, SocketFlags.None, ReceiveCb, readBuff);
}
catch (Exception e) {
// recvText.text += "连接已断开";
socket.Close();
status = Status.None;
}

}

private void ProcessData() {
if (buffCount < sizeof(Int32))
return;
Array.Copy(readBuff, lenByte, sizeof(Int32));
msgLength = BitConverter.ToInt32(lenByte, 0);
if (buffCount < msgLength + sizeof(Int32))
return;
ProtocolBase protocol = assistProtolByte.Decode(readBuff, sizeof(Int32), msgLength);
lock(msgHandle.msgList) {
msgHandle.msgList.Add(protocol);
}
int count = buffCount - msgLength - sizeof(Int32);
Array.Copy(readBuff, sizeof(Int32) + msgLength, readBuff, 0, count);
buffCount = count;
if (buffCount > 0)
ProcessData();
}

public bool Close() {
try {
socket.Close();
return true;
}
catch (Exception e) {
Debug.Log("关闭失败:" + e.Message);
return false;
}
}

public bool SendMsg( ProtocolBase protol) {
string proName = protol.GetName(); ;
return SendMsg(protol, proName);

}
public bool SendMsg(ProtocolBase protol,string protolName) {
if (status != Status.Connect) {
Debug.Log("404 Not Found");
return false;
}
ProtocolByte protocolByte1 = new ProtocolByte();
protocolByte1.AddString(protolName);
byte[] protolNameByte = protocolByte1.bytes;
byte[] b = protol.Encode();
byte[] len1 = BitConverter.GetBytes(protolNameByte.Length + b.Length);
byte[] sendByte = len1.Concat(protolNameByte).Concat(b).ToArray();
socket.Send(sendByte);
Debug.Log(GetStr(sendByte));
return true;
}
public string GetStr(byte[] bytes) {
string str = "";
if (bytes == null) return str;
for (int i = 0; i < bytes.Length; i++) {
int b = (int)bytes[i];
str += b.ToString() + " ";
}
return str;
}
#region 地址辅助方法
public string GetClientAddress() {
return socket.LocalEndPoint.ToString();
}

public string GetLocalIp() {
///获取本地的IP地址
string AddressIP = string.Empty;
foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList) {

if (_IPAddress.AddressFamily.ToString() == "InterNetwork") {

AddressIP = _IPAddress.ToString();
}
}
return AddressIP;
}
#endregion
}

消息处理类

在处理消息队列时一定需要上lock

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MsgHandle
{
public int num = NetCloudClientManager.instance.HandleMsgNum;
public List<ProtocolBase> msgList = new List<ProtocolBase>();

ProtocolByte assistProtocol;


public void Running() {
while(msgList.Count>0&&num>0) {
num--;
//处理长度和将协议分开
assistProtocol = msgList[0] as ProtocolByte;
if(assistProtocol==null) {
Debug.Log("消息转化失败");
lock (msgList) {
msgList.RemoveAt(0);
}
return;
}
string protocolName=assistProtocol.GetName();
int protocolNameLen=System.Text.Encoding.UTF8.GetBytes(protocolName).Length + sizeof(Int32);
switch (protocolName) {
case "ProtocolCubeTexture":
ProtocolCubeTexture protocolCubeTexture = new ProtocolCubeTexture();
ProtocolCubeTexture aprotocol = protocolCubeTexture.Decode(assistProtocol.bytes, protocolNameLen, assistProtocol.bytes.Length) as ProtocolCubeTexture;
if (aprotocol == null) break;
Vector3 pos = new Vector3(aprotocol.Coord[0], aprotocol.Coord[1], aprotocol.Coord[2]);
PointMessage point = NetCloudClientManager.instance.PM.Find((PointMessage p) => p.pos.Equals(pos));
if(point==null) point = new PointMessage();

point.ResolveToPointMessage(aprotocol.Coord, aprotocol.CubemapFace, aprotocol.srcTexture);

NetCloudClientManager.instance.PM.Add(point);
break;

case "Start":
ProtocolStr protocolStr = new ProtocolStr();
ProtocolStr protocolstr = protocolStr.Decode(assistProtocol.bytes, protocolNameLen, assistProtocol.bytes.Length) as ProtocolStr;
NetCloudClientManager.instance.debug.text += ("\n" + protocolstr.str);
break;
}
lock(msgList) {
msgList.RemoveAt(0);
}
//ProtocolCubeTexture protocol = msgList[0] as ProtocolCubeTexture;
}
num = NetCloudClientManager.instance.HandleMsgNum;
}
}

PointMessage 点消息类

区别于服务端,需要把相应的字节流变成texture,并将其贴到点消息的CubeMap上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class PointMessage {
public Vector3 pos;
public Cubemap cubemap;

static int width;

bool[] FaceFlags ;
int size;
public PointMessage() {
pos = Vector3.zero;
width = NetCloudClientManager.instance.width;
size = 0;
FaceFlags = new bool[] { false, false, false, false, false, false };
cubemap = new Cubemap(width, TextureFormat.RGBA32, false);
}
public void ResolveToPointMessage(byte[] byt ) {
string str = System.Text.Encoding.UTF8.GetString(byt);
string[] strs = str.Split(' ');
pos.x = float.Parse(strs[0]);
pos.y = float.Parse(strs[1]);
pos.z = float.Parse(strs[2]);
string CF = strs[3];
int bytCount = System.Text.Encoding.UTF8.GetBytes(pos.x.ToString() + " " + pos.y.ToString() + " " + pos.z.ToString() + " " + CF + " ").Length;
byte[] image = byt.Skip(bytCount).ToArray();
switch (CF) {
case "PX": cubemap.SetPixels(ColorToCubemap(image), CubemapFace.PositiveX); break;
case "NX": cubemap.SetPixels(ColorToCubemap(image), CubemapFace.NegativeX); break;
case "PY": cubemap.SetPixels(ColorToCubemap(image), CubemapFace.PositiveY); break;
case "NY": cubemap.SetPixels(ColorToCubemap(image), CubemapFace.NegativeY); break;
case "PZ": cubemap.SetPixels(ColorToCubemap(image), CubemapFace.PositiveZ); break;
case "NZ": cubemap.SetPixels(ColorToCubemap(image), CubemapFace.NegativeZ); break;
}
cubemap.Apply();
size++;
//Texture2DClient.LoadImage(image);
//Texture2DClient.Apply();

}

public void ResolveToPointMessage(int[] Coord,int CubeMapFace,Texture2D texture) {
pos.x = Coord[0];
pos.y = Coord[1];
pos.z = Coord[2];
switch (CubeMapFace) {
case 0: cubemap.SetPixels( texture.GetPixels(), CubemapFace.PositiveX); break;
case 1: cubemap.SetPixels( texture.GetPixels(), CubemapFace.NegativeX); break;
case 2: cubemap.SetPixels( texture.GetPixels(), CubemapFace.PositiveY); break;
case 3: cubemap.SetPixels( texture.GetPixels(), CubemapFace.NegativeY); break;
case 4: cubemap.SetPixels( texture.GetPixels(), CubemapFace.PositiveZ); break;
case 5: cubemap.SetPixels( texture.GetPixels(), CubemapFace.NegativeZ); break;
}
Debug.Log("cubeface " + CubeMapFace);


FaceFlags[CubeMapFace] = true;
cubemap.Apply();

}
Color[] ColorToCubemap(byte[] byt) {
Texture2D textureTest = new Texture2D(width, width);
textureTest.LoadImage(byt);
textureTest.Apply();

return textureTest.GetPixels() ;
}

public int GetSize() {
size = 0;
for(int i=0; i<FaceFlags.Length;i++) { if (FaceFlags[i]) size++; }
return size;
}
public void aa() {
Debug.Log("aaaaa");
}
}

协议

个人理解:字节流协议和字符串流协议算是中间层协议,其他协议类可以聚合两个中间层协议进行编写。

协议基类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ProtocolBase
{
//解码器
public virtual ProtocolBase Decode(byte[] readBuff,int start,int length) {
return new ProtocolBase();
}
//编码器
public virtual byte[] Encode() {
return new byte[] { };
}
public virtual string GetName() {
return "Base";
}
public virtual string GetDesc() {
return "";
}
}

字节流协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class ProtocolByte : ProtocolBase {
public byte[] bytes;
public override ProtocolBase Decode(byte[] readBuff, int start, int length) {
ProtocolByte proByte = new ProtocolByte();
proByte.bytes = new byte[length];
Array.Copy(readBuff, start, proByte.bytes, 0, length);
return (ProtocolBase)proByte;
}

public override byte[] Encode() {
return bytes;
}
public override string GetName() {
return GetString(0);
}


public override string GetDesc() {
string str = "";
if (bytes == null) return str;
for(int i=0;i<bytes.Length;i++) {
int b = (int)bytes[i];
str += b.ToString() + " ";
}
return str;
}
#region 字节辅助流
public void AddString(string str) {
Int32 len = str.Length;
byte[] lenBytes = BitConverter.GetBytes(len);
byte[] strBytes = System.Text.Encoding.UTF8.GetBytes(str);
if (bytes == null)
bytes = lenBytes.Concat(strBytes).ToArray();
else
bytes = bytes.Concat(lenBytes).Concat(strBytes).ToArray();

}
public string GetString(int start, ref int end) {
if (bytes == null)
return "";
if (bytes.Length < start + sizeof(Int32))
return "";
Int32 strLen = BitConverter.ToInt32(bytes, start);
if (bytes.Length < start + sizeof(Int32) + strLen)
return "";
string str = System.Text.Encoding.UTF8.GetString(bytes, start + sizeof(Int32) , strLen);
end = start + sizeof(Int32) + strLen;
return str;
}
public string GetString(int start) {
int end = 0;
return GetString(start,ref end);
}


public void AddInt(int num) {
byte[] numBytes = BitConverter.GetBytes(num);
if (bytes == null)
bytes = numBytes;
else
bytes = bytes.Concat(numBytes).ToArray();
}
public int GetInt(int start,ref int end) {
if (bytes == null)
return 0;
if (bytes.Length < start + sizeof(Int32))
return 0;
end = start + sizeof(Int32);
return BitConverter.ToInt32(bytes, start);
}public int GetInt(int start) {

int end = 0;
return GetInt(start,ref end);
}


public void AddFloat(float num) {
byte[] numBytes = BitConverter.GetBytes(num);
if (bytes == null)
bytes = numBytes;
else
bytes = bytes.Concat(numBytes).ToArray();
}
public float GetFloat(int start, ref int end) {
if (bytes == null)
return 0;
if (bytes.Length < start + sizeof(float))
return 0;
end = start + sizeof(float);
return BitConverter.ToSingle(bytes, start);
}
public float GetFloat(int start) {

int end = 0;
return GetFloat(start, ref end);
}
#endregion
}

字符串协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ProtocolStr : ProtocolBase {
public string str;
public override ProtocolBase Decode(byte[] readBuff, int start, int length) {
ProtocolStr proStr = new ProtocolStr();
proStr.str = System.Text.Encoding.UTF8.GetString(readBuff, start, length);
return (ProtocolBase) proStr;
}
public override byte[] Encode() {

return System.Text.Encoding.UTF8.GetBytes(str);
}
public override string GetName() {
if (str.Length == 0) return "";
return str.Split(',')[0];
}
public override string GetDesc() {
return str;
}
}

ProtocolCubeTexture 协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using System;

public class ProtocolCubeTexture : ProtocolBase {
public int width = NetCloudClientManager.instance.width;


public int[] Coord = new int[] { 0, 0, 0 };
public Texture2D srcTexture;
public int CubemapFace = -1;

//解码器
public override ProtocolBase Decode(byte[] readBuff, int start, int length) {
ProtocolCubeTexture proTexture = new ProtocolCubeTexture();
ProtocolByte proByte = new ProtocolByte();
proByte.bytes = readBuff;
for(int i=0;i<3;i++) {
proTexture.Coord[i] = proByte.GetInt(start, ref start);
}
proTexture.CubemapFace = proByte.GetInt(start, ref start);

//图片解析
int srcStart = start;
int srcLength = readBuff.Length-start;
byte[] srcbyte = new byte[srcLength];
Array.Copy(readBuff, srcStart, srcbyte, 0, srcLength);
proTexture.srcTexture = new Texture2D(width,width);
proTexture.srcTexture.LoadImage(srcbyte);
proTexture.srcTexture.Apply();
//NetCloudClientManager.instance.tex[proTexture.CubemapFace] = proTexture.srcTexture;
return (ProtocolBase) proTexture;
}

//编码器
public override byte[] Encode() {

//立方体面编译

ProtocolByte proByte = new ProtocolByte();

for(int i=0;i<3;i++) {
proByte.AddInt(Coord[i]);
}
proByte.AddInt(CubemapFace);
byte[] cubeFaceBytes = proByte.Encode();
//图片编译
if (srcTexture == null)
return null;
byte[] srcTextureByte = srcTexture.EncodeToJPG();
//byte[] lenByte = BitConverter.GetBytes(srcTextureByte.Length + cubeFaceBytes.Length);
byte[] byt = cubeFaceBytes.Concat(srcTextureByte).ToArray();
return byt;
}
public override string GetName() {

return "ProtocolCubeTexture";
}
public override string GetDesc() {
string str = "";
byte[] srcTextureByte = srcTexture.EncodeToJPG();
if (srcTextureByte == null) return str;
for (int i = 0; i < srcTextureByte.Length; i++) {
int b = (int)srcTextureByte[i];
str += b.ToString() + " ";
}
return str;
}
}