0

この例に従って、同期 HTTP サーバー (.NET の HttpListener を使用) を非同期に変換しました。それは機能しますが、Google Chrome から発行するすべてのリクエストに対して、アドレス バーで Enter キーを押すか、F5 を押すと、2 つのリクエストが返されます。最初のものは完全に処理され、応答はブラウザーで適切にレンダリングされます。

ただし、表示されるべきではない 2 番目の要求には、空のクエリ文字列があります (私のサーバーはコンソール アプリケーションであるため、Console.WriteLine.

サーバーが同期のときはこのようなことは起こらなかったので、非同期モデルに移行するときに何かを台無しにしたに違いありません。

コードは次のとおりです。

using System;
using System.Diagnostics;
using System.Net;

namespace MyWebServer{

    internal static class MyHTTPServer {
        private static int mPortNumber = 7091;
        private static HttpListener mListener;
        private static MyCustomHttpHandler mHttpHandler;

        //Omitted some auxiliary methods to print stuff to Console,
        //like WriteError and WriteRequestHeaderInformation

        public static void Main( String[] pArg ) {
            AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
            HttpHandler = new MyCustomHttpHandler();
            mPortNumber = Convert.ToInt32( pArg[0] );
            Console.WriteLine( "Starting the HttpListener on port:{0}", mPortNumber );
            InitialiseListener();
            Console.WriteLine( "Listener started on port: {0}, waiting for requests.", mPortNumber );
            Console.WriteLine( "Listening. Press Enter to stop." );
            Console.ReadLine();
            if( mListener.IsListening )
                mListener.Stop();
        }

        private static void InitialiseListener() {
            try {
                mListener = new HttpListener {
                    AuthenticationSchemes = AuthenticationSchemes.Basic
                };
                string prefix = string.Format( "http://+:{0}/", mPortNumber );
                mListener.Prefixes.Add( prefix );
                mListener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
                mListener.Start();
                mListener.BeginGetContext( RequestReceived, null );
            } catch( Exception ex ) {
                WriteError( ex.Message );
            }
        }

        private static void RequestReceived( IAsyncResult result ) {
            var timer = new Stopwatch();
            Console.WriteLine( "---Request Received----" );
            timer.Reset();
            timer.Start();
            //Retrieve context; on error, print message and wait for another request
            HttpListenerContext context = null;
            try {
                context = mListener.EndGetContext( result );
            } catch( HttpListenerException e ) {
                WriteError( e.ToString() );
                if( mListener.IsListening )
                    mListener.BeginGetContext( RequestReceived, null );
                return;
            }
            //Process request and send response
            mListener.BeginGetContext( RequestReceived, null );
            try {
                WriteRequestHeaderInformation( context );
                CreateResponseDocument( context );
            } catch( Exception ex ) {
                WriteError( ex.Message );
            }
            Console.WriteLine( "----Request processed in {0} milliseconds ----", timer.ElapsedMilliseconds );
        }

        private static void CreateResponseDocument( HttpListenerContext pHttpListenerContext ) {
            try {
                byte[] htmlOutput = HttpHandler.ProcessRequest( pHttpListenerContext.Request.Url.LocalPath.Replace( "/", "" ), pHttpListenerContext.Request.Url.Query.Replace( "?", "" ) );
                if( htmlOutput != null && pHttpListenerContext.Response.OutputStream.CanWrite ) {
                    pHttpListenerContext.Response.Headers.Add( "Access-Control-Allow-Origin", "*" );
                    //pHttpListenerContext.Response.ContentType = "image/jpg";
                    pHttpListenerContext.Response.ContentType = "text/plain";
                    pHttpListenerContext.Response.OutputStream.Write( htmlOutput, 0, htmlOutput.Length );
                }
                pHttpListenerContext.Response.Close();
            } catch( Exception ex ) {
                WriteError( ex.Message );
            }
        }    
    }
}
4

1 に答える 1

0

これは、応答が単なるバイトの集まり (この場合は jpeg 画像を表す) である場合にのみ発生するようです。アドレスバーに http リクエストを直接入力する代わりに、次のような HTML ページを開くと...

 <html>
     <head/>
        <body>
            <img src="http://localhost:serverPort/queryParametersGoHere" />
        </body>
</html>

... 1 つだけの要求がサーバーによって受信されます。(私は自分のポートとパラメーターを匿名化しました。queryParametersGoHere と書かれている場所には、実際には がありました?param1=value1&param2=value2

于 2012-12-19T14:13:02.427 に答える