/// <summary>
/// Socket通讯工具类
/// 约定:
/// 一个数据包前8个字节为数据长度【长度不包括数据包前面的12个字节】,[支持4G大文件]
/// 中间的4个字节为数据类别: 1为Json,2为文件
/// 后面的均为 “数据”
/// </summary>
public class SocketTools
{
private static int JSON_TYPE = 1;
private static int FILE_TYPE = 2;
private readonly string mIp;
private readonly int mPort;
private Socket mClient;
private bool mDeviceConnected;
/// <summary>
/// 当前连接状态:是否已经连接
/// </summary>
public bool Connected
{
get
{
try
{
if (this.mClient != null
&& this.mClient.Connected
&& this.mClient.Poll(100, SelectMode.SelectWrite))
{
return true;
}
}
catch (Exception)
{ }
return false;
}
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="ip">ip地址</param>
/// <param name="port">端口号</param>
public SocketTools(string ip, int port)
{
this.mIp = ip;
this.mPort = port;
this.mDeviceConnected = true;
}
/// <summary>
/// 连接服务器
/// </summary>
/// <returns></returns>
public SocketResult ConnectServer()
{
if (!this.mDeviceConnected)
return SocketResult.Error("设备已断开连接");
this.DisConnect();
try
{
//1.创建发送者
this.mClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//2.连接给谁发送
this.mClient.Connect(IPAddress.Parse(this.mIp), this.mPort);
this.mClient.SendBufferSize = 102400;
this.mClient.ReceiveBufferSize = 102400;
}
catch (Exception e)
{
return SocketResult.Error(e.Message);
}
return SocketResult.Success();
}
/// <summary>
/// 断开Socket连接
/// </summary>
/// <returns></returns>
public SocketResult DisConnect()
{
try
{
if (this.mClient != null && this.mClient.Connected)
this.mClient.Close();
}
catch (Exception e)
{
return SocketResult.Error(e.Message);
}
this.mClient = null;
return SocketResult.Success();
}
public void DeviceDisConnect()
{
mDeviceConnected = false;
this.DisConnect();
}
/// <summary>
/// 向服务端发送Json格式数据,返回Json格式数据
/// </summary>
/// <param name="json"></param>
/// <returns></returns>
public SocketResult SendJsonReceiveJson(SocketModel json)
{
SocketResult tmp = Connect();
if (!tmp.Result)
return tmp;
try
{
SendJson(json);
return CheckReceiveJson(json);
}
catch (Exception e)
{
return SocketResult.Error(e.Message);
}
}
/// <summary>
/// 向服务端发送Json格式数据,返回文件
/// 用于下载手机端的文件
/// </summary>
/// <param name="json"></param>
/// <returns></returns>
public SocketResult SendJsonReceiveFile(SocketModel json)
{
SocketResult tmp = Connect();
if (!tmp.Result)
return tmp;
try
{
SendJson(json);
return ReceiveFile();
}
catch (Exception e)
{
return SocketResult.Error(e.Message);
}
}
/// <summary>
/// 向服务端发送文件格式数据,返回Json
/// 向手机端上传文件
/// </summary>
/// <param name="json"></param>
/// <param name="fileName"></param>
/// <returns></returns>
public SocketResult SendFileReceiveModel(SocketModel json, string fileName)
{
SocketResult tmp = Connect();
if (!tmp.Result)
return tmp;
// 先发送Json 后发送文件
try
{
if (!File.Exists(fileName))
{
return SocketResult.Error("文件不存在,无法发送文件");
}
SendJson(json);
SendFile(fileName);
return CheckReceiveJson(json);
}
catch (Exception e)
{
return SocketResult.Error(e.Message);
}
}
private SocketResult Connect()
{
if (!this.Connected && this.ConnectServer().Result)
{
return SocketResult.Error("设备已断开连接");
}
return SocketResult.Success();
}
private void SendFile(string fileName)
{
using (FileStream fs = File.OpenRead(fileName))
{
if (fs.Length > int.MaxValue)
{
fs.Close();
throw new Exception("文件过大,无法发送");
}
this.mClient.Send(BitConverter.GetBytes(fs.Length));
this.mClient.Send(BitConverter.GetBytes(FILE_TYPE));
while (fs.Position < fs.Length - 1)
{
byte[] tempBuffer = new byte[102400];
int tempLen = fs.Read(tempBuffer, 0, tempBuffer.Length);
// 空文件 不必Send
if (tempLen > 0)
this.mClient.Send(tempBuffer, 0, tempLen, SocketFlags.None);
}
fs.Close();
}
}
private SocketResult ReceiveFile()
{
string tempDownloadFile = Path.GetTempFileName();
try
{
using (FileStream fsDownload = File.Create(tempDownloadFile))
{
if (!this.Read(fsDownload, FILE_TYPE))
{
LogTools.Info("接收数据失败", "Receive File");
return SocketResult.Error("接收数据失败");
}
string tempFile = Path.GetTempFileName();
if (fsDownload.Length > 12)
{
fsDownload.Seek(12, SeekOrigin.Begin);
using (FileStream fs = File.Create(tempFile))
{
// 循环写入 每次100K
while (fsDownload.Position < fsDownload.Length - 1)
{
byte[] tempBuffer = new byte[102400];
int tempLen = fsDownload.Read(tempBuffer, 0, tempBuffer.Length);
fs.Write(tempBuffer, 0, tempLen);
}
fs.Flush();
fs.Close();
}
}
fsDownload.Close();
LogTools.Info("接收文件成功", "Receive File");
// 文件下载成功后 将临时文件 文件全路径返回
SocketResult result = SocketResult.Success();
result.Model = new SocketModel();
result.Model.AddData(SocketModel.PathKey, tempFile);
return result;
}
}
catch (Exception ex)
{
LogTools.Execption(ex, "Receive File");
throw ex;
}
finally
{
try
{
File.Delete(tempDownloadFile);
}
catch { }
}
}
private void SendJson(SocketModel json)
{
byte[] data = JsonTools.SerializeToBuffer(json);
if (data == null || data.Length == 0)
throw new ArgumentNullException(" data is empty ");
string log = string.Format(" Cmd:[{0}] JSON:[{1}] ", json.Cmd.ToString().PadRight(10, ' '), JsonTools.SerializeToString(json));
LogTools.Info(log, "Send JSON");
this.mClient.Send(BitConverter.GetBytes((long)data.Length));
this.mClient.Send(BitConverter.GetBytes(JSON_TYPE));
this.mClient.Send(data);
}
private SocketResult ReceiveJson()
{
try
{
using (MemoryStream ms = new MemoryStream())
{
if (!this.Read(ms, JSON_TYPE) || ms.Length <= 12)
{
LogTools.Info("接收数据失败", "Receive JSON");
return SocketResult.Error("接收数据失败");
}
SocketResult socketResult = null;
byte[] buffer = new byte[ms.Length - 12];
ms.Seek(12, SeekOrigin.Begin);
ms.Read(buffer, 0, (int)ms.Length - 12);
SocketModel model = JsonTools.DeserializeToTFromBuffer<SocketModel>(buffer);
string log = string.Format(" JSON:[{0}] ", JsonTools.SerializeToString(model));
LogTools.Info(log, "Receive JSON");
if (model == null || model.Result == 0)
{
socketResult = SocketResult.Error(model == null ? "数据格式错误" : model.Msg);
socketResult.Model = model;
return socketResult;
}
socketResult = SocketResult.Success();
socketResult.Model = model;
return socketResult;
}
}
catch (Exception ex)
{
LogTools.Execption(ex, "Receive JSON");
throw ex;
}
}
private SocketResult CheckReceiveJson(SocketModel json)
{
SocketResult result = ReceiveJson();
if (result.Result && json.Cmd != result.Model.Cmd)
{
result.Result = false;
result.Msg = "问答命令不一致";
LogTools.Monitor(string.Format(" SendModel.Cmd:[{0}] ", json.Cmd), "问答命令不一致");
}
return result;
}
private bool Read(Stream stream, int type)
{
while (true)
{
long next = GetNextCount(stream);
if (next < 0)
{
this.DisConnect();
return false;
}
if (next == 0)
{
stream.Seek(8, SeekOrigin.Begin);
byte[] typeBuffer = new byte[4];
stream.Read(typeBuffer, 0, 4);
if (type != BitConverter.ToInt32(typeBuffer, 0))
{
this.DisConnect();
return false;
}
break;
}
long len = stream.Length;
ReadBuffer(stream, (int)next);
// 判断本次读取是否成功
if (stream.Length == len)
{
this.DisConnect();
return false;
}
}
return true;
}
private void ReadBuffer(Stream stream, int next)
{
try
{
byte[] buffer = new byte[next];
int len = 0;
if (this.mClient.Connected)
len = this.mClient.Receive(buffer, next, SocketFlags.None);
if (len > 0)
{
stream.Seek(0, SeekOrigin.End);
stream.Write(buffer, 0, len);
stream.Flush();
}
}
catch (Exception)
{ }
}
private long GetNextCount(Stream stream)
{
// 确定nextCount
long next = 0;
if (stream.Length < 12)
{
next = 12;
}
else
{
stream.Seek(0, SeekOrigin.Begin);
byte[] lenBuffer = new byte[8];
stream.Read(lenBuffer, 0, 8);
try
{
long len = BitConverter.ToInt64(lenBuffer, 0);
if (len < 0)
return -1;
next = (len + 12 - stream.Length);
}
catch (Exception)
{
return -1;
}
}
// 每次最多读取100K
if (next > 102400)
next = 102400;
return next;
}
}
/// <summary>
/// Socket命令类别
/// </summary>
public enum ESocketCmdType
{
/// <summary>
/// 下载文件
/// </summary>
GetFile = 1,
/// <summary>
/// 获取手机端的照片列表
/// </summary>
GetPicList = 2,
/// <summary>
/// 获取手机端的音乐列表
/// </summary>
GetMusicList = 3,
/// <summary>
/// 获取通讯录列表
/// </summary>
GetAddressListList = 4,
/// <summary>
/// 获取短信列表
/// </summary>
GetSMSList = 5,
/// <summary>
/// 上传文件
/// </summary>
UploadFile = 999,
}
/// <summary>
/// Socket通讯,Json实体类
/// </summary>
public class SocketModel
{
public static readonly string DefaultKey = "Default";
public static readonly string ParamKey = "Param";
public static readonly string PathKey = "Path";
/// <summary>
/// 命令
/// </summary>
[JsonProperty("Cmd")]
public ESocketCmdType Cmd;
/// <summary>
/// 1:成功 0:失败
/// </summary>
[JsonProperty("Result")]
public int Result;
/// <summary>
/// 提示信息
/// </summary>
[JsonProperty("Msg")]
public string Msg;
/// <summary>
/// 命令附带参数
/// </summary>
[JsonProperty("Data")]
public Dictionary<string, object> Data;
public SocketModel()
{
this.Msg = string.Empty;
this.Data = new Dictionary<string, object>();
}
public SocketModel AddData(string key, object value)
{
if (this.Data != null && !this.Data.ContainsKey(key))
this.Data.Add(key, value);
return this;
}
public string GetString(string key)
{
if (this.Data != null && this.Data.ContainsKey(key) && this.Data[key] != null)
return this.Data[key].ToString().Trim();
return string.Empty;
}
public int GetInt(string key)
{
int result = -1;
if (!int.TryParse(GetString(key), out result))
result = -1;
return result;
}
public double GetDouble(string key)
{
double result = -1;
if (!double.TryParse(GetString(key), out result))
result = -1;
return result;
}
public T GetObject<T>(string key) where T : class
{
if (this.Data != null && this.Data.ContainsKey(key))
return this.Data[key] as T;
return null;
}
public Dictionary<string, object> GetDictionary(string key)
{
if (this.Data != null && this.Data.ContainsKey(key))
return JsonTools.Deserialize(this.Data[key]);
return null;
}
public Dictionary<string, string> GetDictionaryString(string key)
{
if (this.Data != null && this.Data.ContainsKey(key))
return JsonTools.DeserializeToTFromObject<Dictionary<string, string>>(this.Data[key]);
return null;
}
public T GetObjectFromJson<T>(string key) where T : class
{
if (this.Data != null && this.Data.ContainsKey(key))
return JsonTools.DeserializeToTFromObject<T>(this.Data[key]);
return null;
}
}
/// <summary>
/// Socket通讯结果
/// </summary>
public class SocketResult
{
/// <summary>
/// 操作是否成功
/// </summary>
public bool Result;
/// <summary>
/// 失败时的错误提示信息
/// </summary>
public string Msg;
/// <summary>
/// 服务端返回的数据
/// </summary>
public SocketModel Model;
private SocketResult()
{ }
public static SocketResult Success()
{
SocketResult result = new SocketResult();
result.Result = true;
result.Msg = "操作成功";
return result;
}
public static SocketResult Error(string msg)
{
SocketResult result = new SocketResult();
result.Result = false;
result.Msg = msg;
return result;
}
}