using LJLib.D; using LJLib.Net.SPI.Com; using LJLib.Net.SPI.Server; using LJLib.Text.Parser; using LJLib.Tools.Helper; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Net.Sockets; using System.Text; using System.Threading; namespace LJLib.TcpHandle { internal class P1Server : TcpHandler, IRemoteInfoContainer { private ILJServer _server = null; private const byte NEW_ALLGZIP = 0x10; private const byte SVRBEAT = 0x08; private const byte PROTOCOL_FLAG = 0x04; private const byte READ_GZIP = 0x02; private const byte WRITE_GZIP = 0x01; private const int JsonMaxLen = 0x14000000; private const int FileNameMaxLen = 0x01400000; private const int FileMaxLen = 0x28000000; private byte headByte = 0x00; private string apiName = string.Empty; private LJParser parser = new LJParser(); public P1Server(TcpClient client, ILJServer server) : base(client) { _server = server; } protected override void DataArrived() { headByte = _reader.ReadByte(); if (headByte == 0) { return; } if (headByte > 0x1F || (headByte & PROTOCOL_FLAG) != PROTOCOL_FLAG) { throw new Exception("不支持协议" + headByte.ToString("X2")); } if ((headByte & NEW_ALLGZIP) == NEW_ALLGZIP) { if ((headByte & READ_GZIP) != READ_GZIP) { throw new Exception("协议异常:新协议必须压缩发送"); } if ((headByte & WRITE_GZIP) != WRITE_GZIP) { throw new Exception("协议异常:新协议必须压缩返回"); } } DebugHelper.Start("ReadJsonStr"); BinaryReader reader = null; GZipStream stream = null; MemoryStream ms = null; if ((headByte & READ_GZIP) == READ_GZIP) { if ((headByte & NEW_ALLGZIP) == NEW_ALLGZIP) { var allen = new byte[4]; _ns.Read(allen, 0, allen.Length); var len = BitConverter.ToInt32(allen, 0); ms = new MemoryStream(); StreamHelper.StreamCopy(ms, _ns, len); Debug.Write("ReadFromNet End"); ms.Seek(0, SeekOrigin.Begin); stream = new GZipStream(ms, CompressionMode.Decompress, false); reader = new BinaryReader(stream); } else { stream = new GZipStream(_ns, CompressionMode.Decompress, true); reader = new BinaryReader(stream); } } else { reader = new BinaryReader(_ns); } bool hasRslt = false; object syncRoot = new object(); Timer timer = null; if ((headByte & SVRBEAT) == SVRBEAT) { timer = new Timer(state => { if (hasRslt) { timer.Dispose(); return; } lock (syncRoot) { if (!hasRslt) { try { _writer.Write(false); } catch (Exception) { } } } }, null, 3000, 3000); } using (ms) using (stream) using (timer) try { var len = reader.ReadInt32(); if (len > JsonMaxLen) { throw new Exception(string.Format("请求Json字符串长度不能大于{0:#,##0.##}M", (double)JsonMaxLen / 1024 / 1024)); } if (len <= 0) { throw new Exception("Json字符串长度不能小于等于0"); } var str = Encoding.UTF8.GetString(reader.ReadBytes(len)); DebugHelper.Stop("ReadJsonStr"); var index = str.IndexOf('{'); if (index <= 0) { throw new Exception("协议错误"); } apiName = str.Substring(0, index); var body = str.Substring(index); Debug.Write(string.Format("Request:{0}:{1}", apiName, body)); DebugHelper.Start("ReadRequestFiles_" + apiName); Type requestType = _server.GetRequestType(apiName); Dictionary files = new Dictionary(); var filecnt = reader.ReadInt16(); if (filecnt < 0) { throw new Exception("文件数不能小于0"); } if (filecnt > 1000) { throw new Exception("文件数不能大于1000"); } for (int i = 0; i < filecnt; i++) { var strlen = reader.ReadInt32(); if (strlen > FileNameMaxLen) { throw new Exception(string.Format("文件名长度不能大于{0:#,##0.##}M", (double)FileNameMaxLen / 1024 / 1024)); } if (strlen <= 0) { throw new Exception("文件名长度不能小于等于0"); } var filename = Encoding.UTF8.GetString(reader.ReadBytes(strlen)); var filelen = reader.ReadInt32(); if (filelen > FileMaxLen) { throw new Exception(string.Format("文件大小不能大于{0:#,##0.##}M", (double)FileMaxLen / 1024 / 1024)); } if (filelen <= 0) { throw new Exception("文件大小不能小于等于0"); } var filedata = reader.ReadBytes(filelen); files.Add(filename, filedata); } if (stream != null) { stream.Close(); } DebugHelper.Stop("ReadRequestFiles_" + apiName); DebugHelper.Start("JsonToRequest_" + apiName); ILJRequest request = parser.JsonParse(requestType, body, files) as ILJRequest; DebugHelper.Stop("JsonToRequest_" + apiName); DebugHelper.Start("DoExcute_" + apiName); LJResponse rslt = null; try { rslt = _server.DoExcute(request, this); if (!string.IsNullOrEmpty(rslt.ErrMsg)) { Trace.Write(apiName + "返回错误信息:" + rslt.ErrMsg); } } catch (System.Exception ex) { Trace.Write(ex.ToString()); rslt = new ErrResponse(ex.ToString()); } DebugHelper.Stop("DoExcute_" + apiName); if ((headByte & SVRBEAT) == SVRBEAT) { lock (syncRoot) { hasRslt = true; _writer.Write(true); } } WriteResponse(headByte, rslt); } catch (Exception ex) { Trace.Write(ex.ToString()); var errRsp = new ErrResponse { ErrCode = "exp", ErrMsg = ex.ToString() }; if ((headByte & SVRBEAT) == SVRBEAT) { lock (syncRoot) { hasRslt = true; _writer.Write(true); } } WriteResponse(headByte, errRsp); throw; } } private void WriteResponse(byte headByte, LJResponse rslt) { DebugHelper.Start("ResponseToJson_" + apiName); BinaryWriter writer = null; GZipStream ostream = null; MemoryStream ms = null; if ((headByte & WRITE_GZIP) == WRITE_GZIP) { ms = new MemoryStream(); writer = new BinaryWriter(ms); } else { writer = new BinaryWriter(_ns); } var ofiles = new Dictionary(); var strrslt = parser.ToJson(rslt, ofiles); byte ofilecnt = 0; DebugHelper.Stop("ResponseToJson_" + apiName); Debug.Write("ResponseToJson End"); if (ofiles.Count > byte.MaxValue) { DebugHelper.Start("返回文件数太多_" + apiName); var ErrMsg = "返回文件数太多,超过255个:" + ofiles.Count; Trace.Write(ErrMsg); ofiles.Clear(); strrslt = parser.ToJson(new ErrResponse { ErrCode = "", ErrMsg = ErrMsg }); ofilecnt = (byte)ofiles.Count; DebugHelper.Stop("返回文件数太多_" + apiName); } else { ofilecnt = (byte)ofiles.Count; } Debug.Write(strrslt);//把返回的东西写入log DebugHelper.Start("WriteResponseToMS_" + apiName); var rsltbytes = Encoding.UTF8.GetBytes(strrslt); writer.Write(rsltbytes.Length); writer.Write(rsltbytes); writer.Write(ofilecnt); writer.Flush(); foreach (var file in ofiles) { var filenamebytes = Encoding.UTF8.GetBytes(file.Key); writer.Write(filenamebytes.Length); writer.Write(filenamebytes); writer.Write(file.Value.Length); writer.Write(file.Value); writer.Flush(); } DebugHelper.Stop("WriteResponseToMS_" + apiName); Debug.Write("WriteResponseToMS End"); if ((headByte & WRITE_GZIP) == WRITE_GZIP) { DebugHelper.Start("MS_To_GZip_" + apiName); var gzipms = NewGzipms(ms); // DONE: GZIP压缩是否有问题 var L = gzipms.ReadByte(); var magic = (gzipms.ReadByte() << 8) | L; if (magic != 0x8b1f) { DebugHelper.Start("FixGZipErr_" + apiName); gzipms.Dispose(); gzipms = NewGzipms(ms); L = gzipms.ReadByte(); magic = (gzipms.ReadByte() << 8) | L; if (magic != 0x8b1f) { Trace.Write("GZIPFormatErr:" + BitConverter.ToString(ms.ToArray())); } DebugHelper.Stop("FixGZipErr_" + apiName); } ms.Dispose(); DebugHelper.Stop("MS_To_GZip_" + apiName); Debug.Write("MS_To_GZip End"); if ((headByte & NEW_ALLGZIP) == NEW_ALLGZIP) { var allen = BitConverter.GetBytes((int)gzipms.Length); _ns.Write(allen, 0, allen.Length); Debug.Write("WriteLen End-" + gzipms.Length); } DebugHelper.Start("WriteGzipToNet_" + apiName); gzipms.Seek(0, SeekOrigin.Begin); StreamHelper.StreamCopy(_ns, gzipms); gzipms.Dispose(); DebugHelper.Stop("WriteGzipToNet_" + apiName); Debug.Write("WriteGzipToNet End"); } } private static MemoryStream NewGzipms(MemoryStream ms) { var gzipms = new MemoryStream(); var gzipstream = new GZipStream(gzipms, CompressionMode.Compress, true); ms.Seek(0, SeekOrigin.Begin); StreamHelper.StreamCopy(gzipstream, ms); gzipstream.Dispose(); gzipms.Seek(0, SeekOrigin.Begin); return gzipms; } public string RemoteInfo { get { try { return _client.Client.RemoteEndPoint.ToString(); } catch (Exception ex) { Trace.Write(ex.ToString()); return null; } } } } }