using LJLib.Net.SPI.Client; using LJLib.Tools.Helper; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Text; using System.Threading; namespace LJLib.Client { public sealed class P1Client : ILJClient { 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 Stream _stream = null; private object syncRoot = new object(); public P1Client(Stream stream) { _stream = stream; } public string DoExcute(string apiName, string requestJSON) { lock (syncRoot) { var apiname = apiName; var firstByte = new[] { (byte)(SVRBEAT | PROTOCOL_FLAG | READ_GZIP | WRITE_GZIP | NEW_ALLGZIP), (byte)(SVRBEAT | PROTOCOL_FLAG | READ_GZIP | WRITE_GZIP), (byte)(SVRBEAT | PROTOCOL_FLAG), }; var headByte = firstByte[0]; 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("协议异常:新协议必须压缩返回"); } } if (!_stream.CanWrite) { throw new Exception(string.Format("远端服务已中断(不能写)")); } _stream.Write(firstByte, 0, 1); var ostream = _stream; if ((headByte & READ_GZIP) == READ_GZIP) { ostream = new MemoryStream(); } string str = apiname + requestJSON; WriteStringAndFiles(ostream, str, null, null); if ((headByte & READ_GZIP) == READ_GZIP) { using (ostream) using (var gzipms = new MemoryStream()) using (var gzip = new GZipStream(gzipms, CompressionMode.Compress, true)) { ostream.Seek(0, SeekOrigin.Begin); StreamHelper.StreamCopy(gzip, ostream); gzip.Close(); if ((headByte & NEW_ALLGZIP) == NEW_ALLGZIP) { var filelen = BitConverter.GetBytes((int)gzipms.Length); _stream.Write(filelen, 0, filelen.Length); } gzipms.Seek(0, SeekOrigin.Begin); StreamHelper.StreamCopy(_stream, gzipms); } } if (!_stream.CanRead) { throw new Exception(string.Format("远端服务已中断(不能读)")); } if ((headByte & SVRBEAT) == SVRBEAT) { var oldTimeout = _stream.ReadTimeout; _stream.ReadTimeout = 10000; var hasRslt = _stream.ReadByte(); while (hasRslt == 0) { Thread.Sleep(100); if (!_stream.CanRead) { throw new Exception(string.Format("远端服务已中断(不能读)")); } hasRslt = _stream.ReadByte(); if (hasRslt == -1) { throw new Exception(string.Format("远端服务已中断(不能读)")); } } _stream.ReadTimeout = oldTimeout; } Debug.Write("WaitServer End"); var istream = _stream; MemoryStream ms = null; GZipStream gzipstream = null; if ((headByte & WRITE_GZIP) == WRITE_GZIP) { if ((headByte & NEW_ALLGZIP) == NEW_ALLGZIP) { ms = new MemoryStream(); var allen = new byte[4]; _stream.Read(allen, 0, allen.Length); var alen = BitConverter.ToInt32(allen, 0); StreamHelper.StreamCopy(ms, _stream, alen); Debug.Write("ReadResponseFromNet End"); ms.Seek(0, SeekOrigin.Begin); gzipstream = new GZipStream(ms, CompressionMode.Decompress, false); istream = gzipstream; } else { gzipstream = new GZipStream(_stream, CompressionMode.Decompress, true); istream = gzipstream; } } byte[] bytes; Dictionary rfiles = new Dictionary(); using (ms) using (gzipstream) { var reader = new BinaryReader(istream); var len = reader.ReadInt32(); bytes = reader.ReadBytes(len); var filecnt = reader.ReadByte(); for (int i = 0; i < filecnt; i++) { var namelen = reader.ReadInt32(); var namebytes = reader.ReadBytes(namelen); var datalen = reader.ReadInt32(); var databytes = reader.ReadBytes(datalen); rfiles.Add(Encoding.UTF8.GetString(namebytes), databytes); } Debug.Write("ReadResponse End"); } var strrsp = Encoding.UTF8.GetString(bytes); return strrsp; } } private static void WriteStringAndFiles(Stream ostream, string str, IDictionary files, Dictionary exfiles) { var strbytes = Encoding.UTF8.GetBytes(str); var lenbytes = BitConverter.GetBytes(strbytes.Length); ostream.Write(lenbytes, 0, lenbytes.Length); ostream.Write(strbytes, 0, strbytes.Length); ostream.Flush(); if (files == null) { files = new Dictionary(); } if (exfiles == null) { exfiles = new Dictionary(); } var shortbytes = BitConverter.GetBytes((short)(files.Count + exfiles.Count)); ostream.Write(shortbytes, 0, shortbytes.Length); foreach (var file in files) { var namebytes = Encoding.UTF8.GetBytes(file.Key); var namelen = BitConverter.GetBytes(namebytes.Length); ostream.Write(namelen, 0, namelen.Length); ostream.Write(namebytes, 0, namebytes.Length); ostream.Flush(); using (var fs = File.OpenRead(file.Value)) { var filelen = BitConverter.GetBytes((int)fs.Length); ostream.Write(filelen, 0, filelen.Length); byte[] buff = new byte[10240]; int read = 0; while ((read = fs.Read(buff, 0, buff.Length)) > 0) { ostream.Write(buff, 0, read); ostream.Flush(); } } } foreach (var file in exfiles) { var namebytes = Encoding.UTF8.GetBytes(file.Key); var namelen = BitConverter.GetBytes(namebytes.Length); ostream.Write(namelen, 0, namelen.Length); ostream.Write(namebytes, 0, namebytes.Length); ostream.Flush(); var filelen = BitConverter.GetBytes((int)file.Value.Length); ostream.Write(filelen, 0, filelen.Length); using (var ms = new MemoryStream(file.Value)) { byte[] buff = new byte[10240]; int read = 0; while ((read = ms.Read(buff, 0, buff.Length)) > 0) { ostream.Write(buff, 0, read); ostream.Flush(); } } ostream.Flush(); } ostream.Flush(); } public void Beat() { lock (syncRoot) { _stream.WriteByte(0x00); } } public void Dispose() { _stream.Dispose(); } } }