538 lines
17 KiB
C#
538 lines
17 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Net;
|
||
using System.Net.Sockets;
|
||
using System.Text;
|
||
using System.Threading;
|
||
using UnityEngine;
|
||
|
||
/// <summary>
|
||
/// 客户端socket是属于那一种处理方式
|
||
/// </summary>
|
||
public enum OpenClientSocketEnum
|
||
{
|
||
Null,
|
||
客户端,
|
||
服务端
|
||
}
|
||
|
||
public class ClientSocket
|
||
{
|
||
#region 网络模块
|
||
public Socket socket;
|
||
public byte[] readBuff;
|
||
List<byte> cache = new List<byte>();
|
||
public List<string> reciveMessagejosn = new List<string>();//收到的消息列表
|
||
public List<byte[]> sendMessages = new List<byte[]>();//发送列表
|
||
private bool isreading = false;
|
||
public bool threadRun = true;//线程运行控制
|
||
public Action<bool, int> closeExeCallBack = null;//关闭exe回调
|
||
public Action<bool, string> zhiHuiCallBack = null;//指挥回调
|
||
// public Timer timer;
|
||
public byte[] currentMessage;
|
||
public OpenClientSocketEnum openClientSocketEnum;//打开类型
|
||
|
||
public bool success = true;//是否成功发送消息
|
||
|
||
|
||
|
||
public ClientSocket(Socket tmpsocket, OpenClientSocketEnum openClientSocketEnum)
|
||
{
|
||
readBuff = new byte[1024];
|
||
socket = tmpsocket;
|
||
socket.ReceiveTimeout = 8000;
|
||
socket.SendTimeout = 8000;
|
||
this.openClientSocketEnum = openClientSocketEnum;
|
||
// timer = new Timer(TimerCallBack, currentMessage, Timeout.Infinite, 10000);
|
||
}
|
||
|
||
/// <summary>
|
||
///接收数据(线程)
|
||
/// </summary>
|
||
public void BeginRecv()
|
||
{
|
||
UnityEngine.Debug.Log("开始接收消息");
|
||
socket.BeginReceive(readBuff, 0, 1024, SocketFlags.None, ReciveCallBack, readBuff);//开始接收客户端发送字节
|
||
}
|
||
/// <summary>
|
||
/// 接收回调委托
|
||
/// </summary>
|
||
/// <param name="ar"></param>
|
||
public void ReciveCallBack(IAsyncResult ar)
|
||
{
|
||
try
|
||
{
|
||
int length = socket.EndReceive(ar);//接收完成
|
||
byte[] massge = new byte[length];
|
||
//接受0字节关闭socket
|
||
if(length==0)
|
||
{
|
||
if(openClientSocketEnum == OpenClientSocketEnum.客户端)
|
||
{
|
||
threadRun = false;
|
||
if(socket.Connected)
|
||
{
|
||
socket.Shutdown(SocketShutdown.Both);
|
||
}
|
||
socket.Close();
|
||
// ServerSocket.socketList.Remove(this);
|
||
}
|
||
}
|
||
Buffer.BlockCopy(readBuff, 0, massge, 0, length);//拷贝消息
|
||
cache.AddRange(massge);//存储消息
|
||
if (isreading == false)
|
||
{
|
||
isreading = true;
|
||
OnDate();//解析数据
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("数据正在被读");
|
||
}
|
||
if (threadRun == true)
|
||
{
|
||
//递归
|
||
if (socket == null)
|
||
{
|
||
threadRun = false;
|
||
}
|
||
else
|
||
{
|
||
if (!socket.Connected)
|
||
{
|
||
threadRun = false;
|
||
socket.Close();
|
||
}
|
||
}
|
||
|
||
if (socket != null)
|
||
{
|
||
socket.BeginReceive(readBuff, 0, 1024, SocketFlags.None, ReciveCallBack, readBuff);//接收下一条消息
|
||
}
|
||
}
|
||
//else
|
||
//{
|
||
// return;
|
||
//}
|
||
}
|
||
catch(Exception e)
|
||
{
|
||
UnityEngine.Debug.Log("接受线程异常"+e.Message);
|
||
if (openClientSocketEnum == OpenClientSocketEnum.客户端)
|
||
{
|
||
if (fangzhenClient != null && this == fangzhenClient)
|
||
{
|
||
if (!fangzhenClient.socket.Connected)
|
||
{
|
||
//断线重连
|
||
ConnectFangZhenSocekt(LoadManage.Instance.currentPractice.IpAddress, LoadManage.Instance.currentPractice.Port.Value);
|
||
}
|
||
//CloseFangZhenSocket();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 解析消息
|
||
/// </summary>
|
||
public void OnDate()
|
||
{
|
||
//反序列化
|
||
byte[] result = Decode(ref cache);
|
||
|
||
//如果解析完了,重新置为可读
|
||
if (result == null)
|
||
{
|
||
isreading = false;
|
||
return;
|
||
}
|
||
|
||
//消息体解码
|
||
string message = Mdecode(result);
|
||
if (message == null)
|
||
{
|
||
Console.WriteLine("message为空");
|
||
isreading = false;
|
||
return;
|
||
}
|
||
|
||
//存储消息体(json)
|
||
//reciveMessagejosn.Add(message);
|
||
//处理消息
|
||
if (openClientSocketEnum == OpenClientSocketEnum.客户端)
|
||
{
|
||
MessageRecive(message);
|
||
}
|
||
OnDate();//递归,直到全部解析完成
|
||
}
|
||
|
||
/// <summary>
|
||
///消息体长度解码(去头部)
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public byte[] Decode(ref List<byte> cache)
|
||
{
|
||
if (cache.Count < 4)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
MemoryStream ms = new MemoryStream(cache.ToArray());//内存流读写消息
|
||
BinaryReader br = new BinaryReader(ms);//二进制读取
|
||
int length = br.ReadInt32();//读取头部4个字节,得到消息内容长度
|
||
|
||
if (length > ms.Length - ms.Position)//消息不完整
|
||
{
|
||
//UnityEngine.Debug.Log("消息不完整");
|
||
return null;
|
||
}
|
||
byte[] result = br.ReadBytes(length);//光标继续移动,读取消息内容
|
||
|
||
cache.Clear();//清空消息
|
||
cache.AddRange(br.ReadBytes((int)(ms.Length - ms.Position)));//去掉第一个消息
|
||
|
||
br.Close();
|
||
ms.Close();
|
||
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 消息体内容解析(json字符串)
|
||
/// </summary>
|
||
/// <param name="value"></param>
|
||
/// <returns></returns>
|
||
public string Mdecode(byte[] value)
|
||
{
|
||
string jsonStr = Encoding.UTF8.GetString(value);//反序列化为jstring
|
||
return jsonStr;
|
||
}
|
||
/// <summary>
|
||
/// 加入发送队列(改成直接发送消息)
|
||
/// </summary>
|
||
/// <param name="tmpStr"></param>
|
||
public void ReadySend(MessageModel message)
|
||
{
|
||
try
|
||
{
|
||
if(!this.socket.Connected)
|
||
{
|
||
UnityEngine.Debug.Log("未连接,发送失败");
|
||
return;
|
||
}
|
||
if (message == null)
|
||
{
|
||
return;
|
||
}
|
||
//实例化一个消息对象
|
||
|
||
string jsonstr = LitJson.JsonMapper.ToJson(message);
|
||
byte[] ba = Encoding.UTF8.GetBytes(jsonstr);//得到byte[] message
|
||
if (ba.Length == 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
//长度编码
|
||
ByteArray arr = new ByteArray();
|
||
|
||
arr.Write(ba.Length);
|
||
arr.Write(ba);
|
||
|
||
byte[] sendBuffer = arr.GetBuffer();
|
||
socket.Send(sendBuffer);
|
||
}
|
||
catch(Exception e)
|
||
{
|
||
UnityEngine.Debug.Log("发送错误"+e.Message);
|
||
if (openClientSocketEnum == OpenClientSocketEnum.客户端)
|
||
{
|
||
if (fangzhenClient != null && this == fangzhenClient)
|
||
{
|
||
if(!fangzhenClient.socket.Connected)
|
||
{
|
||
//断线重连
|
||
ConnectFangZhenSocekt(LoadManage.Instance.currentPractice.IpAddress, LoadManage.Instance.currentPractice.Port.Value);
|
||
}
|
||
//CloseFangZhenSocket();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 处理消息
|
||
/// </summary>
|
||
public void MessageRecive(string json)
|
||
{
|
||
try
|
||
{
|
||
if (json == null || json == "")
|
||
{
|
||
return;
|
||
}
|
||
MessageModel message = LitJson.JsonMapper.ToObject<MessageModel>(json);
|
||
switch (message.operationEnum)
|
||
{
|
||
case SimOperationEnum.指挥指令服务端:
|
||
//步骤
|
||
if (zhiHuiCallBack != null)
|
||
{
|
||
zhiHuiCallBack(true, message.str);
|
||
zhiHuiCallBack = null;
|
||
}
|
||
else
|
||
{
|
||
// HandleResult._Instance.zhiHuiStr.AddRange(JsonConvert.DeserializeObject<List<string>>(message.str));
|
||
}
|
||
break;
|
||
case SimOperationEnum.科目启停服务端:
|
||
//转发给给服务器
|
||
//HandleResult._Instance.subjectSet.Add(message.str);
|
||
break;
|
||
case SimOperationEnum.科目切换服务端:
|
||
//HandleResult._Instance.changeSubject.Add(message);
|
||
break;
|
||
case SimOperationEnum.操作软件二维端:
|
||
//操作软件发来的
|
||
//SoftManage.Instance.Soft.Add(message);
|
||
break;
|
||
}
|
||
}
|
||
catch(Exception e)
|
||
{
|
||
UnityEngine.Debug.LogWarning(json);
|
||
UnityEngine.Debug.LogWarning(e.Message);
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 协同交互调用模块
|
||
public static ClientSocket fangzhenClient;//客户端socket连接仿真服务器
|
||
|
||
/// <summary>
|
||
/// 连接仿真服务器
|
||
/// </summary>
|
||
public static void ConnectFangZhenSocekt(string serverIP, int port,Action<bool> action=null)
|
||
{
|
||
UnityEngine.Debug.Log("开启仿真服务器客户端socket:"+ serverIP+ ":port");
|
||
if (fangzhenClient!=null && fangzhenClient.socket.Connected)
|
||
{
|
||
UnityEngine.Debug.Log("仿真客户端不为空");
|
||
if (action != null)
|
||
{
|
||
action(true);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
try
|
||
{
|
||
UnityEngine.Debug.Log("正在连接仿真服务器中。。。。");
|
||
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||
socket.Connect(IPAddress.Parse(serverIP), port);
|
||
if (socket.Connected)
|
||
{
|
||
UnityEngine.Debug.Log("连接成功");
|
||
//创建客户端对象
|
||
fangzhenClient = new ClientSocket(socket, OpenClientSocketEnum.客户端);
|
||
//开启异步接收
|
||
fangzhenClient.BeginRecv();
|
||
if (action != null)
|
||
{
|
||
action(true);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (action != null)
|
||
{
|
||
action(false);
|
||
}
|
||
else
|
||
{
|
||
UnityEngine.Debug.Log("连接仿真服务器失败,重新连接");
|
||
ConnectFangZhenSocekt(serverIP, port);
|
||
}
|
||
}
|
||
}
|
||
catch(Exception e)
|
||
{
|
||
UnityEngine.Debug.Log("连接仿真服务器失败,请重试:"+e.Message);
|
||
if (action != null)
|
||
{
|
||
action(false);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 关闭仿真服务器客户端
|
||
/// </summary>
|
||
public static void CloseFangZhenSocket()
|
||
{
|
||
if (fangzhenClient != null)
|
||
{
|
||
fangzhenClient.threadRun = false;
|
||
if (fangzhenClient.socket.Connected)
|
||
{
|
||
fangzhenClient.socket.Shutdown(SocketShutdown.Both);
|
||
}
|
||
fangzhenClient.socket.Close();
|
||
fangzhenClient = null;
|
||
UnityEngine.Debug.Log("关闭仿真服务客户端socket成功");
|
||
}
|
||
}
|
||
|
||
|
||
public static void SendToTongBuFangZhenServerByAllUser(MessageModel message)
|
||
{
|
||
if (fangzhenClient != null)
|
||
{
|
||
if (fangzhenClient.socket.Connected)
|
||
{
|
||
fangzhenClient.ReadySend(message);
|
||
}
|
||
else
|
||
{
|
||
ConnectFangZhenSocekt(LoadManage.Instance.currentPractice.IpAddress, LoadManage.Instance.currentPractice.Port.Value, (a) =>
|
||
{
|
||
if(a)
|
||
{
|
||
fangzhenClient.ReadySend(message);
|
||
}
|
||
else
|
||
{
|
||
UnityEngine.Debug.Log("连接失败");
|
||
}
|
||
});
|
||
}
|
||
}
|
||
else
|
||
{
|
||
try
|
||
{
|
||
UnityEngine.Debug.Log("正在连接仿真服务器中。。。。");
|
||
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||
socket.Connect(IPAddress.Parse(LoadManage.Instance.currentPractice.IpAddress), LoadManage.Instance.currentPractice.Port.Value);
|
||
if (socket.Connected)
|
||
{
|
||
UnityEngine.Debug.Log("连接成功");
|
||
//创建客户端对象
|
||
fangzhenClient = new ClientSocket(socket, OpenClientSocketEnum.客户端);
|
||
//开启异步接收
|
||
fangzhenClient.BeginRecv();
|
||
fangzhenClient.ReadySend(message);
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
UnityEngine.Debug.Log("连接仿真服务器失败,请重试");
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 发送同步数据给仿真服务器
|
||
/// </summary>
|
||
/// <param name="message">发送的消息</param>
|
||
/// <param name="callback">返回的字符串</param>
|
||
public static void SendToTongBuFangZhenServer(MessageModel message)
|
||
{
|
||
if (fangzhenClient != null && fangzhenClient.socket.Connected)
|
||
{
|
||
fangzhenClient.ReadySend(message);
|
||
//UnityEngine.Debug.Log("发送的同步消息内容:__________ " + message.str);
|
||
}
|
||
else
|
||
{
|
||
try
|
||
{
|
||
UnityEngine.Debug.Log("正在连接仿真服务器中。。。。");
|
||
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||
socket.Connect(IPAddress.Parse(LoadManage.Instance.currentPractice.IpAddress), LoadManage.Instance.currentPractice.Port.Value);
|
||
if (socket.Connected)
|
||
{
|
||
UnityEngine.Debug.Log("连接成功");
|
||
//创建客户端对象
|
||
fangzhenClient = new ClientSocket(socket, OpenClientSocketEnum.客户端);
|
||
//开启异步接收
|
||
fangzhenClient.BeginRecv();
|
||
fangzhenClient.ReadySend(message);
|
||
//UnityEngine.Debug.Log("发送的同步消息内容:__________ " + message.str);
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
UnityEngine.Debug.Log("连接仿真服务器失败,请重试");
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 发送命令给仿真服务器
|
||
/// </summary>
|
||
/// <param name="message"></param>
|
||
public static void SendCommondToFangZhenServer(MessageModel message)
|
||
{
|
||
if (fangzhenClient != null && fangzhenClient.socket.Connected)
|
||
{
|
||
fangzhenClient.ReadySend(message);
|
||
}
|
||
else
|
||
{
|
||
try
|
||
{
|
||
UnityEngine.Debug.Log("正在连接仿真服务器中。。。。");
|
||
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||
socket.Connect(IPAddress.Parse(LoadManage.Instance.currentPractice.IpAddress), LoadManage.Instance.currentPractice.Port.Value);
|
||
if (socket.Connected)
|
||
{
|
||
UnityEngine.Debug.Log("连接成功");
|
||
//创建客户端对象
|
||
fangzhenClient = new ClientSocket(socket, OpenClientSocketEnum.客户端);
|
||
//开启异步接收
|
||
fangzhenClient.BeginRecv();
|
||
fangzhenClient.ReadySend(message);
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
UnityEngine.Debug.Log("连接仿真服务器失败,请重试");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发送指挥给仿真服务器
|
||
/// </summary>
|
||
/// <param name="message">发送的消息</param>
|
||
/// <param name="callback">返回的字符串</param>
|
||
public static void SendZhiHuiToFangZhenServer(MessageModel message, Action<bool, string> callback)
|
||
{
|
||
if (fangzhenClient != null && fangzhenClient.socket.Connected)
|
||
{
|
||
fangzhenClient.zhiHuiCallBack = callback;
|
||
fangzhenClient.ReadySend(message);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 同步设备字典
|
||
/// </summary>
|
||
/// <param name="deviceId"></param>
|
||
/// <param name="content"></param>
|
||
public static void DevicesSyncByDic(string deviceId,string content)
|
||
{
|
||
MessageModel message = new MessageModel(SimOperationEnum.数据同步客户端);
|
||
message.str = "设备属性按字典同步字典";
|
||
message.canShu = deviceId +"$"+ content;
|
||
if (fangzhenClient != null && fangzhenClient.socket.Connected)
|
||
{
|
||
fangzhenClient.ReadySend(message);
|
||
}
|
||
}
|
||
#endregion
|
||
}
|