Пример #1
0
        /// <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;
                }
            }
        }
Пример #2
0
        /// <summary>
        /// 打开连接
        /// </summary>
        /// <exception cref="IOException">connection failure</exception>
        /// <exception cref="WebException">web handshake exception</exception>
        /// <returns></returns>
        public void Connection()
        {
            this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                var localEP = this.localEndPoint;
                if (localEP != null)
                {
                    this.socket.Bind(localEP);
                }
                this.socket.Connect(this.host, this.port);
            }
            catch (Exception exception)
            {
                throw new IOException(exception.Message, exception);
            }
            this.stream = new NetworkStream(this.socket, false);

            //header
            var builder = new StringBuilder(128);

            builder.AppendFormat("GET {0} HTTP/1.1", this.Path);
            builder.AppendLine();
            foreach (var item in this.RequestHeader)
            {
                builder.AppendFormat("{0}: {1}", item.Key, item.Value);
                builder.AppendLine();
            }
            //end
            builder.AppendLine();

            //send
            var buffer = this.Encoding.GetBytes(builder.ToString());

            this.stream.Write(buffer, 0, buffer.Length);

            //receive header
            string line;

            string[] harr;
            //HTTP/1.1 101 Switching Protocols
            line = StreamHelper.ReadLine(this.stream, Encoding.ASCII);
            if (!line.StartsWith("HTTP/1.1 101"))
            {
                throw new WebException("Handshake failure, " + line);
            }
            while ((line = StreamHelper.ReadLine(this.stream, Encoding.ASCII)) != null && !line.Equals(string.Empty))
            {
                harr = line.Split(':');
                this.ResponseHeader[harr[0]] = harr[1].Trim();
            }


            //1、如果从服务器接收到的状态码不是101,按HTTP【RFC2616】程序处理响应。在特殊情况下,如果客户端接收到401状态码,可能执行认证;服务器可能用3xx状态码重定向客户端(但不要求客户端遵循他们),等等。否则按下面处理。

            //2、如果响应缺失Upgrade头域或Upgrade头域的值没有包含大小写不敏感的ASCII 值"websocket",客户端必须使WebSocket连接失败。

            //3、如果响应缺失Connection头域或其值不包含大小写不敏感的ASCII值"Upgrade",客户端必须使WebSocket连接失败。

            //4、如果响应缺失Sec-WebSocket-Accept头域或其值不包含 |Sec-WebSocket-Key |(作为字符串,非base64解码的)+ "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"的base64编码 SHA-1值,客户端必须使WebSocket连接失败。

            //5、如果响应包含Sec-WebSocket-Extensions头域,且其值指示使用的扩展不出现在客户端发送的握手(服务器指示的扩展不是客户端要求的),客户端必须使WebSocket连接失败。(解析此头域来决定哪个扩展是要求的在第9.1节描述。)

            //6、如果响应包含Sec-WebSocket-Protocol头域,且这个头域指示使用的子协议不包含在客户端的握手(服务器指示的子协议不是客户端要求的),客户端必须使WebSocket连接失败。


            //check, 此客户端仅验证 Sec-WebSocket-Accept,其它均不处理
            string sec_WebSocket_Accept;

            if (!this.ResponseHeader.TryGetValue("Sec-WebSocket-Accept", out sec_WebSocket_Accept))
            {
                throw new WebException("No Response Sec-WebSocket-Accept");
            }
            if (!this.handshakeSecurityHash09.Equals(sec_WebSocket_Accept))
            {
                throw new WebException("Handshake failure for Sec-WebSocket-Accept");
            }

            //receive
            this.Read();

            //ping start
            this.isConnectioned = true;

            //trigger event
            this.OnConnectioned();
        }
Пример #3
0
        /// <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);
                    }
                }
            }
        }