private void CloseChunkGzip() { var crlfBuffer = this.Encoding.GetBytes("\r\n"); var buffers = new ArraySegment <byte> [4]; // //gzip this.chunkGzipStream.Close(); var contentLength = (int)this.chunkStream.Length; this.chunkStream.Position = 0; contentBuffer = StreamHelper.Receive(this.chunkStream, contentLength); this.chunkStream.SetLength(0); //len var lenBuffer = this.Encoding.GetBytes(contentLength.ToString("x")); buffers[0] = new ArraySegment <byte>(lenBuffer); buffers[1] = new ArraySegment <byte>(crlfBuffer); //content buffers[2] = new ArraySegment <byte>(contentBuffer); buffers[3] = new ArraySegment <byte>(crlfBuffer); // try { this.socket.Send(buffers); } catch { SocketHelper.TryClose(this.socket); StreamHelper.TryClose(this.chunkGzipStream); StreamHelper.TryClose(this.chunkStream); this.chunkWriteEvent.Set(); throw; } }
private void NewAccept(IAsyncResult ar) { Socket socket = null; try { socket = this.listenSocket.EndAccept(ar); } catch { } //new accept try { this.listenSocket.BeginAccept(this.NewAccept, null); } catch (ObjectDisposedException) { } // if (socket != null) { try { ConnectionState connectionState; //keep alive while (true) { connectionState = this.NewConnection(socket); if (connectionState == ConnectionState.KeepAlive) { //next request } else if (connectionState == ConnectionState.Closed) { //close and exit SocketHelper.TryClose(socket); break; } else if (connectionState == ConnectionState.KeepConnection) { //keep connection & exit break; } } } catch (SocketException) { SocketHelper.TryClose(socket); } catch (Exception exception) { SocketHelper.TryClose(socket); this.OnError(exception); } } }
/// <summary> /// Write Chunk Content /// </summary> /// <param name="contentBuffer"></param> private void Chunk(byte[] contentBuffer) { lock (this.chunkWriteEvent) { var crlfBuffer = this.Encoding.GetBytes("\r\n"); var buffers = new ArraySegment <byte> [4]; // int contentLength = contentBuffer.Length; //gzip if (this.acceptGzip && this.gzipThreshold != 0) { this.chunkGzipStream.Write(contentBuffer, 0, contentBuffer.Length); contentLength = (int)this.chunkStream.Length; if (contentLength < 256) { //小字节退出,待下次压缩或关闭压缩 return; } this.chunkStream.Position = 0; contentBuffer = StreamHelper.Receive(this.chunkStream, contentLength); this.chunkStream.SetLength(0); } //len var lenBuffer = this.Encoding.GetBytes(contentLength.ToString("x")); buffers[0] = new ArraySegment <byte>(lenBuffer); buffers[1] = new ArraySegment <byte>(crlfBuffer); //content buffers[2] = new ArraySegment <byte>(contentBuffer); buffers[3] = new ArraySegment <byte>(crlfBuffer); // try { this.socket.Send(buffers); } catch { SocketHelper.TryClose(this.socket); StreamHelper.TryClose(this.chunkGzipStream); StreamHelper.TryClose(this.chunkStream); this.chunkWriteEvent.Set(); throw; } } }
/// <summary> /// connect to host /// </summary> /// <param name="socket"></param> /// <param name="timeout"></param> /// <param name="host"></param> /// <param name="port"></param> /// <exception cref="System.TimeoutException">connect timeout</exception> public static void Connect(Socket socket, string host, int port, int timeout) { using (var eventHandle = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.ManualReset)) { socket.BeginConnect(host, port, ar2 => { try { socket.EndConnect(ar2); // eventHandle.Set(); } catch { } }, null); // if (eventHandle.WaitOne(timeout) == false) { SocketHelper.TryClose(socket); throw new TimeoutException("Connect to " + host + ":" + port + " timeout."); } } }
/// <summary> /// 响应客户端 /// </summary> /// <param name="build"></param> /// <param name="status"></param> protected override void Response(StringBuilder build, HttpStatusCode status) { byte[] contentBuffer = null; byte[] headerBuffer = null; //header if (this.chunkWriteStatus == HttpServerChunkStatus.NoBegin) { if (this.contentBuffer != null) { contentBuffer = this.contentBuffer; } else if (!string.IsNullOrEmpty(this.content)) { contentBuffer = this.Encoding.GetBytes(this.content); } else { contentBuffer = new byte[0]; } //gzip if (this.acceptGzip && this.gzipThreshold != 0 && contentBuffer.Length > this.gzipThreshold) { build.AppendLine("Content-Encoding: gzip"); using (var m = new MemoryStream()) using (var stream = new GZipStream(m, CompressionMode.Compress, true)) { stream.Write(contentBuffer, 0, contentBuffer.Length); stream.Close(); //content contentBuffer = m.ToArray(); } } build.AppendLine(string.Concat("Content-Length: ", contentBuffer.Length)); build.AppendLine(); } else { if (this.acceptGzip && this.gzipThreshold != 0) { build.AppendLine("Content-Encoding: gzip"); } build.AppendLine("Transfer-Encoding: chunked"); build.AppendLine(); } headerBuffer = Encoding.ASCII.GetBytes(build.ToString()); // if (this.chunkWriteStatus == HttpServerChunkStatus.NoBegin) { if (this.isRequestHead == false && contentBuffer != null && contentBuffer.Length > 0) { var buffers = new ArraySegment <byte> [2]; //header buffers[0] = new ArraySegment <byte>(headerBuffer); //content buffers[1] = new ArraySegment <byte>(contentBuffer); //send this.socket.Send(buffers); } else { this.socket.Send(headerBuffer); } } else { try { this.socket.Send(headerBuffer); } catch { SocketHelper.TryClose(this.socket); StreamHelper.TryClose(this.chunkGzipStream); StreamHelper.TryClose(this.chunkStream); throw; } } }
/// <summary> /// End Write /// </summary> /// <exception cref="InvalidOperationException">No Invoke BeginWrite / Has Been Invoked EndWrite</exception> public void EndWrite() { lock (this.chunkWriteEvent) { if (this.chunkWriteStatus == HttpServerChunkStatus.NoBegin) { throw new InvalidOperationException("No Invoke BeginWrite"); } if (this.chunkWriteStatus == HttpServerChunkStatus.End) { throw new InvalidOperationException("Has Been Invoked EndWrite"); } if (this.chunkWriteStatus == HttpServerChunkStatus.Writing) { this.chunkWriteStatus = HttpServerChunkStatus.End; try { //gzip if (this.acceptGzip && this.gzipThreshold != 0) { this.CloseChunkGzip(); } if (this.isRequestHead == false) { var crlfBuffer = this.Encoding.GetBytes("\r\n"); var buffers = new ArraySegment <byte> [3]; using (var m = new MemoryStream(512)) { //len var lenBuffer = this.Encoding.GetBytes("0"); buffers[0] = new ArraySegment <byte>(lenBuffer); buffers[1] = new ArraySegment <byte>(crlfBuffer); //content buffers[2] = new ArraySegment <byte>(crlfBuffer); } // try { this.socket.Send(buffers); } catch { SocketHelper.TryClose(this.socket); throw; } finally { StreamHelper.TryClose(this.chunkGzipStream); StreamHelper.TryClose(this.chunkStream); this.chunkWriteEvent.Set(); } } else { this.chunkWriteEvent.Set(); } } catch (Exception exception) { throw new InvalidOperationException("End check write failure", exception); } } } }
///// <summary> ///// 初始化内容帧 ///// </summary> ///// <param name="buffer"></param> //public WebSocketDataFrame(byte[] buffer) //{ // //帧头 // _header = new WebSocketDataFrameHeader(buffer); // //扩展长度 // if (_header.Length == 126) // { // _extend = new byte[2]; // Buffer.BlockCopy(buffer, 2, _extend, 0, 2); // } // else if (_header.Length == 127) // { // _extend = new byte[8]; // Buffer.BlockCopy(buffer, 2, _extend, 0, 8); // } // //是否有掩码 // if (_header.HasMask) // { // _mask = new byte[4]; // Buffer.BlockCopy(buffer, _extend.Length + 2, _mask, 0, 4); // } // //消息体 // if (_extend.Length == 0) // { // _content = new byte[_header.Length]; // Buffer.BlockCopy(buffer, _extend.Length + _mask.Length + 2, _content, 0, _content.Length); // } // else if (_extend.Length == 2) // { // int contentLength = (int)_extend[0] * 256 + (int)_extend[1]; // _content = new byte[contentLength]; // Buffer.BlockCopy(buffer, _extend.Length + _mask.Length + 2, _content, 0, contentLength > 1024 * 100 ? 1024 * 100 : contentLength); // } // else // { // long len = 0; // int n = 1; // for (int i = 7; i >= 0; i--) // { // len += (int)_extend[i] * n; // n *= 256; // } // _content = new byte[len]; // Buffer.BlockCopy(buffer, _extend.Length + _mask.Length + 2, _content, 0, _content.Length); // } // if (_header.HasMask) _content = Mask(_content, _mask); //} /// <summary> /// 初始化一个Socket数据帧 /// </summary> /// <param name="socket"></param> /// <param name="headerBuffer"></param> public WebSocketDataFrame(Socket socket, byte[] headerBuffer) { //var header = new WebSocketDataFrameHeader(this.headerBuffer); //byte[] extend = new byte[0]; ////扩展长度 //if (header.Length == 126) //{ // extend = SocketHelper.Receive(this.Socket, 2); //} //else if (header.Length == 127) //{ // extend = SocketHelper.Receive(this.Socket, 8); //} ////是否有掩码 //byte[] _mask = null; //if (header.HasMask) //{ // _mask = SocketHelper.Receive(this.Socket, 4); //} ////content length //var content_length = 0L; //if (extend.Length == 0) // content_length = header.Length; //else if (extend.Length == 2) // content_length = (int)extend[0] * 256 + (int)extend[1]; //else //{ // int n = 1; // for (int i = 7; i >= 0; i--) // { // content_length += (int)extend[i] * n; // n *= 256; // } // if (content_length > int.MaxValue) // throw new WebException("Data length transfinite"); //} //var contentBuffer = SocketHelper.Receive(this.Socket, (int)content_length); //if (header.HasMask) //{ // WebSocketDataFrame.Mask(contentBuffer, _mask); //} _header = new WebSocketDataFrameHeader(headerBuffer); //扩展长度 if (_header.Length == 126) { _extend = SocketHelper.Receive(socket, 2); } else if (_header.Length == 127) { _extend = SocketHelper.Receive(socket, 8); } //是否有掩码 if (_header.HasMask) { _mask = SocketHelper.Receive(socket, 4); } //content length var content_length = 0L; if (_extend.Length == 0) { content_length = _header.Length; } else if (_extend.Length == 2) { content_length = (int)_extend[0] * 256 + (int)_extend[1]; } else { int n = 1; for (int i = 7; i >= 0; i--) { content_length += (int)_extend[i] * n; n *= 256; } if (content_length > int.MaxValue) { throw new WebException("Data length transfinite"); } } this.Content = SocketHelper.Receive(socket, (int)content_length); if (_header.HasMask) { Mask(this.Content, _mask); } }
/// <summary> /// 解析POST数扰 /// </summary> /// <param name="socket"></param> /// <param name="context"></param> /// <returns>是否成功</returns> protected virtual bool ParsePostData(Socket socket, HttpServerContext context) { var success = false; var contentLength = 0; int.TryParse(context.RequestHeader["Content-Length"], out contentLength); if (contentLength > context.MaxRequestContentLength) { //请求主体超过限制 if (string.IsNullOrEmpty(context.Content) && context.ContentBuffer == null) { context.Content = "Request Entity Too Large"; } context.Response(HttpStatusCode.RequestEntityTooLarge); } else if (contentLength > 0) { string contentType = context.RequestHeader["Content-Type"]; if (contentType == null) { context.PostData = SocketHelper.Receive(socket, contentLength); success = true; } else if ("application/x-www-form-urlencoded".Equals(contentType, StringComparison.OrdinalIgnoreCase)) { var data = SocketHelper.Receive(socket, contentLength); var postdata = this.encoding.GetString(data); UriHelper.ParseQueryString(postdata, this.encoding, context.Form); success = true; } else if (contentType.IndexOf("multipart/form-data", StringComparison.OrdinalIgnoreCase) != -1) { //"multipart/form-data; boundary=---------------------boundary123data" var boundary = contentType.Substring(contentType.IndexOf("boundary=") + 9); var receiver = new HttpServerMultipartReceiver(socket, boundary, context, contentLength); try { return(receiver.Receive()); } catch (Exception exception) { //请求主体超过限制 if (string.IsNullOrEmpty(context.Content) && context.ContentBuffer == null) { context.Content = "Paser Post Data Failure " + exception.Message; } context.Response(HttpStatusCode.BadRequest); } } else { context.PostData = SocketHelper.Receive(socket, contentLength); success = true; } } else { //要求必要的 Content-Length if (string.IsNullOrEmpty(context.Content) && context.ContentBuffer == null) { context.Content = "Require Content-Length"; } context.Response(HttpStatusCode.LengthRequired); } return(success); }