using Cksoft.Data; using Cksoft.Data.Repository; using Cksoft.Unity; using DllEapDal; using DllEapEntity; using Microsoft.Extensions.Configuration; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; namespace DllEapFileUpload { public class EapSocketServer : IEapScoketServer { Thread threadWatch = null; // 负责监听客户端连接请求的 线程; Socket socketWatch = null; Dictionary dict = new Dictionary(); Dictionary dictThread = new Dictionary(); //string savepath = string.Empty; //byte[] filebytes; //string downloadpath = string.Empty; //byte[] downfilebytes; //string setip = string.Empty; //int setport; public IConfiguration Configuration; //static string serverpath = string.Empty; public bool Start(ref string errinfo) { // 创建负责监听的套接字,注意其中的参数; socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //var builder = new ConfigurationBuilder() // .SetBasePath(Directory.GetCurrentDirectory()) // .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); //Configuration = builder.Build(); //setport = int.Parse(Configuration["EapSocket:SetPort"].ToString()); ////serverpath = Configuration["EapSocket:SaveToServerPath"].ToString(); //try //{ // setip = getEapIpv4(); //} //catch (Exception) //{ // setip = Configuration["EapSocket:SetIp"].ToString(); //} // 获得文本框中的IP对象; //IPAddress address = IPAddress.Parse(setip); // 创建包含ip和端口号的网络节点对象; IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 5777); try { // 将负责监听的套接字绑定到唯一的ip和端口上; socketWatch.Bind(endPoint); } catch (SocketException se) { errinfo = "异常:" + se.Message; LogBLL.Err(errinfo); Close(ref errinfo); return false; } // 设置监听队列的长度; socketWatch.Listen(10); // 创建负责监听的线程; threadWatch = new Thread(WatchConnecting); threadWatch.IsBackground = true; threadWatch.Start(); errinfo = "IEapScoketServer服务器启动监听成功![" + socketWatch.LocalEndPoint.ToString() + "]"; LogBLL.Err(errinfo); return true; } /// /// 监听客户端请求的方法; /// void WatchConnecting() { while (true) // 持续不断的监听客户端的连接请求; { // 开始监听客户端连接请求,Accept方法会阻断当前的线程; Socket sokConnection = socketWatch.Accept(); // 一旦监听到一个客户端的请求,就返回一个与该客户端通信的 套接字; // 将与客户端连接的 套接字 对象添加到集合中; dict.Add(sokConnection.RemoteEndPoint.ToString(), sokConnection); Thread thr = new Thread(ReadSaveFile); thr.IsBackground = true; thr.Start(sokConnection); dictThread.Add(sokConnection.RemoteEndPoint.ToString(), thr); // 将新建的线程 添加 到线程的集合中去。 } } public void ReadSaveFile(object clientSocket) { Socket client = clientSocket as Socket; try { //client.ReceiveTimeout = 1000 * 150; //client.SendTimeout = 1000 * 150; string err = string.Empty; int alllen = 0; byte[] datas = ReadData(client, ref alllen, ref err);//待机程序监听到请求 if (datas == null) { LogBLL.Err(err); return; } else { //byte[] tempstr = new byte[alllen - 32]; //Array.Copy(datas, 32, tempstr, 0, tempstr.Length); byte[] statusdatas = new byte[4]; Array.Copy(datas, 4, statusdatas, 0, 4); //Array.Reverse(statusdatas);//20200920 int status = BitConverter.ToInt32(statusdatas, 0); if (status == 1)//上传 { byte[] getmd5 = new byte[32]; Array.Copy(datas, 8, getmd5, 0, 32); string md5 = Encoding.UTF8.GetString(getmd5); byte[] other = new byte[alllen - 32 - 8]; Array.Copy(datas, 40, other, 0, other.Length); //DllFileSoc.SocketEntity sockE = null; int result=SaveToFile(client, md5, other,ref err); if(result<=0) LogBLL.Err(err); } else if (status == 2)//下载 { byte[] other = new byte[alllen - 8]; Array.Copy(datas, 8, other, 0, other.Length); int result = DownToFile(client, other, ref err); if (result <= 0) LogBLL.Err(err); } else if (status == 5888)//根据机台通信,获取IP、MAC更新数据库机台的RealIP { int result = CheckEapRealIP(client, ref err); if (result <= 0) LogBLL.Err(err); } } } catch (Exception ex) { LogBLL.Err(ex.Message.ToString()); } } private byte[] ReadData(Socket CurrSocket, ref int alllen, ref string errorinfo) { byte[] allbuffs = null; try { int zerocount = 0;//等待设置 int levlen = 4; int result = 0; byte[] tempbuff = new byte[4]; byte[] bytesbuff = new byte[4]; while (levlen > 0) { //说明前面4位还没接受完,需要继续接受 result = CurrSocket.Receive(tempbuff, levlen, SocketFlags.None);//先读取4位块长度字节 if (result == 0 && zerocount <= 20) { zerocount++; //如果返回数据长度为0,则休眠1秒钟,然后继续读取 Thread.Sleep(1000); continue; } if (result <= 0) { errorinfo = $"未能从机台上读取数据,可能机台已经断开了,接受长度={result} "; return null; } if (result > 0) { Array.Copy(tempbuff, 0, bytesbuff, 4 - levlen, result); } levlen = levlen - result; } //Array.Reverse(bytesbuff);//20200920 //byte[] alldatas = BitConverter.GetBytes(20122); //int len11 = BitConverter.ToInt32(alldatas, 0); //获取总长度 int len = BitConverter.ToInt32(bytesbuff, 0) - 4; alllen = len; //if (len > 10) //{ // int a = 10; //} //定义总长度的bytes byte[] buffs = new byte[len]; tempbuff = new byte[len]; levlen = len; zerocount = 0; while (levlen > 0) { //说明还没接受完,需要继续接受 result = CurrSocket.Receive(tempbuff, levlen, SocketFlags.None); //if (result < levlen) //{ // //添加测试代码 // //int a = 10; //} if (result == 0 && zerocount <= 20) { zerocount++; //如果返回数据长度为0,则休眠1秒钟,然后继续读取 Thread.Sleep(1000); continue; } if (result <= 0) { errorinfo = $"未能从机台上读取数据,可能机台已经断开了,接受长度={result} "; return null; } if (result > 0) { Array.Copy(tempbuff, 0, buffs, len - levlen, result); } levlen = levlen - result; } //result =mysocket.Receive(buffs,len,SocketFlags.None); //Array.Reverse(bytesbuff);//20200920 allbuffs = new byte[len + 4]; Array.Copy(bytesbuff, allbuffs, 4); Array.Copy(buffs, 0, allbuffs, 4, len); alllen = len + 4; return allbuffs; } catch (SocketException ex) { errorinfo = $"Socket接受数据发生异常,错误信息为:" + ex.SocketErrorCode.ToString(); return null; } catch (Exception ex) { errorinfo = ex.Message.ToString(); errorinfo = $"Socket接受数据发生异常,错误信息为:" + errorinfo; return null; } } /// /// 组成发送包 /// /// 1=上传 2=下载 /// 1=OK -1=失败 2=文件byte[]传服务器 /// 实体类 /// private byte[] GetFileDatas(Int32 mode, Int32 result, BusinessFile bf) { byte[] BusinessFilebytes = EntityHelper.SerializeBytes(bf); Int32 len = BusinessFilebytes.Length + 12; byte[] alldatas = BitConverter.GetBytes(len); byte[] forAll = (alldatas.Concat(BitConverter.GetBytes(mode)).Concat(BitConverter.GetBytes(result)).Concat(BusinessFilebytes)).ToArray(); return forAll; } private byte[] GetFileDatas(Int32 mode, Int32 result, string msg) { byte[] msgbytes = Encoding.UTF8.GetBytes(msg); Int32 len = msgbytes.Length + 12; byte[] alldatas = BitConverter.GetBytes(len); byte[] forAll = (alldatas.Concat(BitConverter.GetBytes(mode)).Concat(BitConverter.GetBytes(result)).Concat(msgbytes)).ToArray(); return forAll; } private byte[] GetFileDatasMd5(string md5) { byte[] msgbytes = Encoding.UTF8.GetBytes(md5); Int32 len = msgbytes.Length + 4; byte[] alldatas = BitConverter.GetBytes(len); byte[] forAll = (alldatas.Concat(msgbytes)).ToArray(); return forAll; } private byte[] GetFileDatas(Int32 mode, Int32 result, byte[] files) { //byte[] msgbytes = Encoding.UTF8.GetBytes(msg); Int32 len = files.Length + 12; byte[] alldatas = BitConverter.GetBytes(len); byte[] forAll = (alldatas.Concat(BitConverter.GetBytes(mode)).Concat(BitConverter.GetBytes(result)).Concat(files)).ToArray(); return forAll; } //private void SaveToFile(Socket client, string md5, byte[] other) //{ // //FileStream MyFileStream = null; // //SocketEntity sockE = new SocketEntity(); // IDatabase db = null; // Dictionary dic = new Dictionary(); // try // { // db = DbFactory.Base("eap"); // db.BeginTrans(); // string str = ""; // //MemoryStream thisms = new MemoryStream(other); // //sockE = EntityHelper.DeSerializeBytes(other); // // var STR = System.Text.Encoding.UTF8.GetString(other); // dic = EntityHelper.DeSerializeBytes>(other); // BusinessFile bf = new BusinessFileDal(db).UpdownFileForMd5(md5, dic["fileName"], dic["macCode"], "", "", ref str); // //BusinessFile bf = new BusinessFileDal(db).UpdownFileForMd5(md5, sockE.FileName, sockE.MacCode, sockE.Remark, sockE.UserId, ref str); // if (bf != null)//服务器文件已存在,不需要上传 // { // byte[] datas = GetFileDatas(1, 1, bf); // client.Send(datas); // } // else // { // //不存在则上传 // byte[] datas = GetFileDatas(1, 2, "需要上传文件内容"); // //byte[] datas = GetFileDatas(1, 2, bf); // client.Send(datas);//发送需要上传文件的包 // string err = string.Empty; // int alllen = 0; // byte[] afterdatas = ReadData(client, ref alllen, ref err); // byte[] filebytes = new byte[alllen - 4]; // Array.Copy(afterdatas, 4, filebytes, 0, alllen - 4); // BusinessFile endbf = new BusinessFileDal(db).UpdownFileForFile(filebytes, dic["fileName"], dic["macCode"], ref str); // byte[] enddatas = GetFileDatas(1, 1, endbf); // client.Send(enddatas);//发送上传成功的包 // } // db.Commit(); // } // catch (Exception ex) // { // db.Rollback(); // LogBLL.Err($"上传文件保存到服务器失败:", ex); // } // finally // { // if (db != null) // db.Close(); // } //} private int SaveToFile(Socket client, string md5, byte[] other,ref string errorinfo) { //FileStream MyFileStream = null; //SocketEntity sockE = new SocketEntity(); IDatabase db = null; Dictionary dic = new Dictionary(); try { db = DbFactory.Base("eap"); db.BeginTrans(); string str = ""; //MemoryStream thisms = new MemoryStream(other); //sockE = EntityHelper.DeSerializeBytes(other); // var STR = System.Text.Encoding.UTF8.GetString(other); dic = EntityHelper.DeSerializeBytes>(other); BusinessFile bf = new BusinessFileDal(db).UpdownFileForMd5(md5, dic["fileName"], dic["macCode"], "", "", ref str); //BusinessFile bf = new BusinessFileDal(db).UpdownFileForMd5(md5, sockE.FileName, sockE.MacCode, sockE.Remark, sockE.UserId, ref str); if (bf != null)//服务器文件已存在,不需要上传 { byte[] datas = GetFileDatas(1, 1, bf); client.Send(datas); return 1; } else { //不存在则上传 byte[] datas = GetFileDatas(1, 2, "需要上传文件内容"); //byte[] datas = GetFileDatas(1, 2, bf); client.Send(datas);//发送需要上传文件的包 string err = string.Empty; int alllen = 0; byte[] afterdatas = ReadData(client, ref alllen, ref err); byte[] filebytes = new byte[alllen - 4]; Array.Copy(afterdatas, 4, filebytes, 0, alllen - 4); BusinessFile endbf = new BusinessFileDal(db).UpdownFileForFile(filebytes, dic["fileName"], dic["macCode"], ref str); byte[] enddatas = GetFileDatas(1, 1, endbf); client.Send(enddatas);//发送上传成功的包 } db.Commit(); return 1; } catch (Exception ex) { //db.Rollback(); errorinfo = ex.Message.ToString(); return -1; } finally { if (db != null) db.Close(); } } private int DownToFile(Socket client, byte[] other, ref string errorinfo) { //FileStream MyFileStream = null; //string errinfo = string.Empty; Dictionary dic = new Dictionary(); try { //string filename = Encoding.UTF8.GetString(file); //using (MyFileStream = new FileStream(filename, FileMode.Open, FileAccess.Read)) //{ // long size = MyFileStream.Length; // byte[] array = new byte[size]; // MyFileStream.Read(array, 0, array.Length); // MyFileStream.Close(); // byte[] datas = GetFileDatas(2, 1, array); // //client.Send(datas); // if (!SendData(client,datas,ref errorinfo)) // { // return -1; // } //} //return 1; dic = EntityHelper.DeSerializeBytes>(other); string serverfullpath = dic["serverFullpath"]; string clientMd5 = dic["clientMd5"]; string filename = dic["serverFilename"]; byte[] filedatas = GetDownToFileDatas(client, serverfullpath, ref errorinfo); byte[] datas = null; if (filedatas == null) { datas = GetFileDatas(2, -1, errorinfo); } else { if (CheckDownLoadMD5(clientMd5, filedatas, ref errorinfo))//说明客户端有该文件,不需要下载 { errorinfo = "客户端已存在该文件[" + filename + "],无需下载!"; datas = GetFileDatas(2, 3, errorinfo); } else { datas = GetFileDatas(2, 1, filedatas); } } if (!SendData(client, datas, ref errorinfo)) { return -1; } return 1; } catch (Exception ex) { errorinfo = ex.Message.ToString(); return -1; } //finally //{ // if (MyFileStream!=null) // { // MyFileStream.Close(); // } //} } /// /// 获取当前通信的机台IP、Mac更新EAP机台的realIP /// /// /// /// private int CheckEapRealIP(Socket client, ref string errorinfo) { try { string remoteIP = (client.RemoteEndPoint as IPEndPoint).Address.ToString(); string remoteMAC = ArpTool.GetIpFromMac(remoteIP); LogBLL.Err("当前建立通信的IP:" + remoteIP + ";MAC地址:" + remoteMAC); byte[] datas = null; if (remoteIP.Trim().Length<1 || remoteMAC.Trim().Length<1) { errorinfo = "[当前通信异常:缺失IP或MAC]IP:" + remoteIP + ";MAC地址:" + remoteMAC; datas = GetFileDatas(5888, -1, errorinfo); } else { Machine mac = new Machine { MacAddress = remoteMAC, RealIP = remoteIP }; if (UpdateRealIP(mac,ref errorinfo)<0) { datas = GetFileDatas(5888, -1, errorinfo); } else { datas = GetFileDatas(5888, 1, errorinfo); } } if (!SendData(client, datas, ref errorinfo)) { return -1; } return 1; } catch (Exception ex) { errorinfo = ex.Message.ToString(); return -1; } } public int UpdateRealIP(Machine Ma, ref string errorinfo) { using (IDatabase db = DbFactory.Base("eap")) { db.BeginTrans(); var dal = new MachineDal(db); int id = dal.UpdateRealIPForMac(Ma,ref errorinfo); if (id < 0) { db.Rollback(); return -1; } else { db.Commit(); errorinfo = $"根据机台MAC地址:{Ma.MacAddress},更新RealIP:{Ma.RealIP}成功!!!"; } return 1; } } private bool CheckDownLoadMD5(string clientMd5, byte[] file, ref string errorinfo) { try { string serverMd5 = GetMD5HashFromFile(file); if (clientMd5==serverMd5) { return true; } else { return false; } } catch (Exception ex) { errorinfo = ex.Message.ToString(); return false; } } private byte[] GetDownToFileDatas(Socket client, string filename, ref string errorinfo) { FileStream MyFileStream = null; //string errinfo = string.Empty; try { //string filename = Encoding.UTF8.GetString(file); using (MyFileStream = new FileStream(filename, FileMode.Open, FileAccess.Read)) { long size = MyFileStream.Length; byte[] array = new byte[size]; MyFileStream.Read(array, 0, array.Length); MyFileStream.Close(); //byte[] datas = GetFileDatas(2, 1, array); //return datas; return array; } } catch (Exception ex) { errorinfo = ex.Message.ToString(); return null; } finally { if (MyFileStream != null) { MyFileStream.Close(); } } } private bool SendData(Socket CurrSocket, byte[] allbytes, ref string errorinfo) { try { //包的大小 1MB int PacketSize = 1024*1024; //包的数量 int PacketCount = (int)(allbytes.Length / ((long)PacketSize)); //最后一个包的大小 int LastDataPacket = (int)(allbytes.Length - ((long)(PacketSize * PacketCount))); int satrtNum = 1; int len = PacketCount; byte[] sendArr = null; while (len > 0) { sendArr = new byte[PacketSize]; Array.Copy(allbytes, (satrtNum - 1) * PacketSize, sendArr, 0, PacketSize); //CurrSocket.Send(sendArr);//发送文件内容 if (!SendDataIt(CurrSocket, sendArr, ref errorinfo)) return false; len = len - 1; satrtNum++; } if (LastDataPacket != 0) { sendArr = new byte[LastDataPacket]; Array.Copy(allbytes, PacketCount * PacketSize, sendArr, 0, LastDataPacket); //CurrSocket.Send(sendArr);//发送最后一个包 if (!SendDataIt(CurrSocket, sendArr, ref errorinfo)) return false; } return true; } catch (SocketException ex) { errorinfo = "Socket发送数据发生异常,错误信息为:" + ex.SocketErrorCode.ToString(); return false; } catch (Exception ex) { errorinfo = ex.Message.ToString(); errorinfo = "Socket发送数据发生异常,错误信息为:" + errorinfo; return false; } } private bool SendDataIt(Socket CurrSocket, byte[] allbytes, ref string errorinfo) { try { int lenlev = allbytes.Length; byte[] tempbytes = null; int result = 0; while (lenlev > 0) { tempbytes = new byte[lenlev]; Array.Copy(allbytes, allbytes.Length - lenlev, tempbytes, 0, lenlev); result = CurrSocket.Send(tempbytes);//发送文件内容 lenlev = lenlev - result; } return true; } catch (SocketException ex) { errorinfo = "Socket发送数据发生异常,错误信息为:" + ex.SocketErrorCode.ToString(); return false; } catch (Exception ex) { errorinfo = ex.Message.ToString(); errorinfo = "Socket发送数据发生异常,错误信息为:" + errorinfo; return false; } } public bool Close(ref string errinfo) { return ShutDownSocket(socketWatch, ref errinfo); } static void ShutDownSocket(Socket sk, FileStream fs) { if (sk != null) { sk.Close(); //关闭套接字 } if (fs != null) { fs.Close();//关闭文件流 } } //关闭连接 public bool ShutDownSocket(Socket sk, ref string errinfo) { try { if (sk == null) { return true; } else { sk.Close();//关闭Socket sk = null; return true; } } catch (Exception ex) { sk = null; errinfo += ex.Message; return false; } } /// /// 获取当前IPV4地址 /// /// public string getEapIpv4() { string ipv4 = ""; string name = Dns.GetHostName(); IPAddress[] ipadrlist = Dns.GetHostAddresses(name); foreach (IPAddress ipa in ipadrlist) { if (ipa.AddressFamily == AddressFamily.InterNetwork) { ipv4 = ipa.ToString(); break; } } return ipv4; } public static string GetMD5HashFromFile(byte[] filedatas) { try { System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); byte[] retVal = md5.ComputeHash(filedatas); StringBuilder sb = new StringBuilder(); for (int i = 0; i < retVal.Length; i++) { sb.Append(retVal[i].ToString("x2")); } return sb.ToString(); } catch (Exception ex) { //errorinfo = ex.Message.ToString(); return ""; } } } }