using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Net;
using System.Net.Sockets;
public class NetWorkSocket : MonoBehaviour
{
#region 单利模式
private static NetWorkSocket _ins;
public static NetWorkSocket Ins
{
get
{
if (_ins == null)
{
GameObject obj = new GameObject("NetWorkSocket");
DontDestroyOnLoad(obj);
_ins = obj.GetOrAddComponent<NetWorkSocket>();
}
return _ins;
}
}
#endregion
private Socket socket;
#region 发送消息字段
private Queue<byte[]> msgs = new Queue<byte[]>();
private Action checkMsgs;
private int compressSize = 200;
#endregion
#region 接收消息字段
private byte[] buffer = new byte[10240];
private MMO_MemoryStream ms = new MMO_MemoryStream();
private Queue<byte[]> msgsRecive = new Queue<byte[]>();
private int reciveCount = 0;
#endregion
private void Update()
{
while (true)
{
if (reciveCount <= 5)
{
reciveCount++;
lock (msgsRecive)
{
if (msgsRecive.Count > 0)
{
byte[] buffer = msgsRecive.Dequeue();
byte[] bufferNew = new byte[buffer.Length - 3];
bool isCompress = false;
ushort crc = 0;
using (MMO_MemoryStream ms = new MMO_MemoryStream(buffer))
{
isCompress = ms.ReadBool();
crc = ms.ReadUShort();
ms.Read(bufferNew, 0, bufferNew.Length);
}
ushort crcNew = Crc16.CalculateCrc16(bufferNew);
Debug.Log("验证密码:" + crcNew);
if (crc == crcNew)
{
bufferNew = SecurityUtil.Xor(bufferNew);
if (isCompress)
{
bufferNew = ZlibHelper.DeCompressBytes(bufferNew);
}
byte[] bufferContent = new byte[bufferNew.Length - 2];
ushort proCode = 0;
using (MMO_MemoryStream ms = new MMO_MemoryStream(bufferNew))
{
//协议编码
proCode = ms.ReadUShort();
ms.Read(bufferContent, 0, bufferContent.Length);
EventDispatcher.Instance.Dispatch(proCode, bufferContent);
}
}
}
else
{
break;
}
}
}
else
{
reciveCount = 0;
break;
}
}
}
#region 建立Socket连接
public void Connect(string ip, int port)
{
if (socket != null && socket.Connected) return;
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
socket.Connect(new IPEndPoint(IPAddress.Parse(ip), port));
checkMsgs = OnCheckMsgsCallBack;
print("链接成功");
RecevieMsg();
}
catch (Exception e)
{
print("链接失败" + e.Message);
}
}
#endregion
#region 处理发送数据
public void SendMsg(byte[] data)
{
byte[] SendData = CreateData(data);
lock (msgs)
{
msgs.Enqueue(SendData);
checkMsgs.BeginInvoke(null, null);
}
}
public byte[] CreateData(byte[] data)
{
byte[] retBuffer;
//1.压缩
bool isCompress = data.Length > 200 ? true : false;
if (isCompress)
{
data = ZlibHelper.DeCompressBytes(data);
}
//2.异或
data = SecurityUtil.Xor(data);
//3.CRC校验
ushort crc = Crc16.CalculateCrc16(data);
using (MMO_MemoryStream ms = new MMO_MemoryStream())
{
ms.WriteUShort((ushort)(data.Length + 3));
ms.WriteBool(isCompress);
ms.WriteUShort(crc);
ms.Write(data, 0, data.Length);
retBuffer = ms.ToArray();
}
return retBuffer;
}
private void OnCheckMsgsCallBack()
{
lock (msgs)
{
if (msgs.Count > 0)
{
Send(msgs.Dequeue());
}
}
}
private void Send(byte[] data)
{
socket.BeginSend(data, 0, data.Length, SocketFlags.None, SendCallBack, null);
}
private void SendCallBack(IAsyncResult ar)
{
socket.EndSend(ar);
checkMsgs();
}
#endregion
#region 处理接收数据
private void RecevieMsg()
{
//异步接收数据
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallBack, null);
}
private void ReceiveCallBack(IAsyncResult ar)
{
try
{
int len = socket.EndReceive(ar);
if (len > 0)
{
//接收到的数据
//把接收到的数据写入缓存流的尾部
ms.Position = ms.Length;
//指定长度的字节写入流
ms.Write(buffer, 0, len);
if (ms.Length > 2)
{
while (true)
{
ms.Position = 0;
int msgLength = ms.ReadUShort();
int totalLength = 2 + msgLength;
if (ms.Length >= totalLength)
{
byte[] data = new byte[msgLength];
ms.Position = 2;
ms.Read(data, 0, msgLength);
lock (msgsRecive)
{
msgsRecive.Enqueue(data);
}
//处理剩余的字节数组
int remainLength = (int)ms.Length - totalLength;
if (remainLength > 0)
{
byte[] bufferRemain = new byte[remainLength];
ms.Position = totalLength;
ms.Read(bufferRemain, 0, remainLength);
ms.Position = 0;
ms.SetLength(0);
ms.Write(bufferRemain, 0, bufferRemain.Length);
bufferRemain = null;
}
else
{
ms.Position = 0;
ms.SetLength(0);
break;
}
}
else
{
break;
}
}
}
RecevieMsg();
}
else
{
Debug.Log(string.Format("服务器{0}断开连接", socket.RemoteEndPoint.ToString()));
}
}
catch (Exception e)
{
Debug.Log(string.Format("服务器{0}断开连接", socket.RemoteEndPoint.ToString()));
}
}
#endregion
#region 断开连接
private void OnDestroy()
{
if (socket != null && socket.Connected)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
}
#endregion
}
Socket通信
最新推荐文章于 2022-09-06 17:16:36 发布