如何关闭对Griffin.WebServer的请求的连接?

时间:2014-11-26 00:40:45

标签: c# dotnet-httpclient

我们使用Griffin.WebServer替代.Net HttpClient,因为httpclient需要提升权限。在完成了关于该主题的选项后,我们决定使用Griffin.WebServer。抱歉,这没有用Griffin.WebServer标记 - 我没有代表创建该标签。

这个简单的网络服务器响应请求,效果很好 - 一次。然后连接保持打开状态,直到我强行关闭连接(使用TCPView并右键单击 - 关闭连接),或者超时后,后续请求才会处理。

以下是我正在测试的客户:

    static void Main(string[] args)
    {
        try
        {
            var request = new
            {
                JsonData1 = 50538,
                JsonData2 = 2,
                JsonData3 = 1
            };

            var handler = new HttpClientHandler();
            handler.UseDefaultCredentials = true;
            using (var client = new HttpClient(handler))
            {
                client.BaseAddress = new Uri("http://ALocalMachine:8800/listener/");
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                client.DefaultRequestHeaders.ConnectionClose = true;
                Task<HttpResponseMessage> postTask = client.PostAsJsonAsync("RunTest/", request);

                postTask.Wait();

                if (!postTask.Result.IsSuccessStatusCode)
                {
                    throw new Exception("Unable to start test run - " + postTask.Result.ReasonPhrase);
                }

                var responseTask = postTask.Result.Content.ReadAsStringAsync();
                responseTask.Wait();
                dynamic response = JsonConvert.DeserializeObject(responseTask.Result);

                var results = new
                {
                    Error = "",
                    Success = true
                };
            }

            // this request fails with connection forcebly closed
            var request = new
            {
                JsonData1 = 50539,
                JsonData2 = 3,
                JsonData3 = 4
            };

            var handler = new HttpClientHandler();
            handler.UseDefaultCredentials = true;
            using (var client = new HttpClient(handler))
            {
                client.BaseAddress = new Uri("http://ALocalMachine:8800/listener/");
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                client.DefaultRequestHeaders.ConnectionClose = true;
                Task<HttpResponseMessage> postTask = client.PostAsJsonAsync("RunTest/", request);

                postTask.Wait();

                if (!postTask.Result.IsSuccessStatusCode)
                {
                    throw new Exception("Unsuccessful - " + postTask.Result.ReasonPhrase);
                }

                var responseTask = postTask.Result.Content.ReadAsStringAsync();
                responseTask.Wait();
                dynamic response = JsonConvert.DeserializeObject(responseTask.Result);

                var results = new
                {
                    Error = "",
                    Success = true
                };
            }

            Console.WriteLine("successful");
        }
        catch (Exception ex)
        {
            Console.WriteLine("failed with error: " + ex.ToString());
        }

        Console.ReadLine();
    }

以下是Griffin IWorkerModule。

public class MyModule : IWorkerModule
{
    public class ListenerNotifyEventArgs : EventArgs
    {
        public IHttpContext Context { get; set; }
    }

    public delegate void ListenerNotifyEventHandler(object sender, ListenerNotifyEventArgs e);

    public event ListenerNotifyEventHandler OnListenerNotify;

    public void BeginRequest(IHttpContext context)
    {
    }

    public void EndRequest(IHttpContext context)
    {
    }

    public void HandleRequestAsync(IHttpContext context, Action<IAsyncModuleResult> callback)
    {
        // Since this module only supports sync
        callback(new AsyncModuleResult(context, HandleRequest(context)));
    }

    public ModuleResult HandleRequest(IHttpContext context)
    {
        if (OnListenerNotify != null)
            OnListenerNotify(null, new ListenerNotifyEventArgs(){Context = context});

        return ModuleResult.Stop;
    }
}

这是我的听众回调。添加:

    context.Response.KeepAlive = false;

没有任何区别......

    private void ListenerCallback(object sender, MyModule.ListenerNotifyEventArgs eventArgs)
    {
        var context = eventArgs.Context;

        try
        {
            var requestDetails = context.Request.Uri.AbsolutePath.Substring("/TestifyAgent/".Length);

            if (requestDetails.ToLower().StartsWith("runtest"))
            {
                var data_text = new StreamReader(context.Request.Body, context.Request.ContentEncoding).ReadToEnd();

                dynamic requestVals = JsonConvert.DeserializeObject(data_text);
                int jsonData1 = Convert.ToInt32(requestVals.JsonData1);
                int jsonData2 = Convert.ToInt32(requestVals.JsonData2);
                int jsonData3 = Convert.ToInt32(requestVals.JsonData3);

                StartProcess(jsonData1, jsonData2, jsonData3);

                var returnData = new
                {
                    Result = "Success",
                    Environment.MachineName,
                    runRequest.TestCaseRunId
                };
                var returnJsonData = JsonConvert.SerializeObject(returnData);
                var returnUtfData = Encoding.UTF8.GetBytes(returnJsonData);

                context.Response.StatusCode = (int) HttpStatusCode.OK;
                context.Response.StatusDescription = "OK";
                context.Response.ContentType = "text/html";
                context.Response.Body = new MemoryStream();
                context.Response.Body.Write(returnUtfData, 0, returnUtfData.Length);
                context.Response.Body.Flush();
                context.Response.Body.Position = 0;
                context.Response.KeepAlive = false;
                return;
            }
            else
            {
                var buffer = Encoding.UTF8.GetBytes("<html><head></head><body><h1>500 - Server Error</h1></body></html>");
                context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;
                context.Response.StatusDescription = "Bad Request";
                context.Response.ContentType = "text/html";
                context.Response.Body = new MemoryStream();
                context.Response.Body.Write(buffer, 0, buffer.Length);
                context.Response.Body.Flush();
                context.Response.Body.Position = 0;
                context.Response.KeepAlive = false;

                Notify("Invalid Request method:" + context.Request.Method + " Url: " + context.Request.Uri.AbsoluteUri);
                return;
            }
        }
        catch (Exception ex)
        {
            TrySendErrorOrWriteEventLog(ex);

            try
            {
                var buffer =
                    Encoding.UTF8.GetBytes("<html><head></head><body><h1>500 - Server Error</h1>Error processing request:" +
                    context.Request.Method + " Error: " + ex.Message + "</body></html>");
                context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;
                context.Response.StatusDescription = "Internal Server Error";
                context.Response.ContentType = "text/html";
                context.Response.Body.Write(buffer, 0, buffer.Length);
                context.Response.Body.Flush();
                context.Response.Body.Position = 0;
            }
            catch { }
            return;
        }
    }

修改 我会保留这个以防万一有人需要它(并得到答案 - jgauffin?),但是,我找到了一个简单的解决方案来创建一个不需要提升权限的监听器at this CodeProject page。这是一个非常简单的解决方案,只需一次更改即可。我遇到的一个问题是它不会关闭。它需要将它添加到监听器循环中:

public abstract class SimpleHttpServer {

    protected int port;
    private TcpListener _listener;

    // this lets us call in with Listener.Server.Close(); when we want to shutdown
    public TcpListener Listener { get { return _listener; } }
    public bool IsActive { get; set; }

    public SimpleHttpServer(int port) 
    {
        this.port = port;
    }

    public void listen()
    {
        IsActive = true;
        _listener = new TcpListener(port);
        _listener.Start();
        while (IsActive) 
        {
            try
            {
                TcpClient s = _listener.AcceptTcpClient();
                SimpleHttpProcessor processor = new SimpleHttpProcessor(s, this);
                Thread thread = new Thread(new ThreadStart(processor.process));
                thread.Start();
                Thread.Sleep(1);
            }
            catch (Exception ex)
            {   // shutdown requested?
                if (ex.Message.Contains("A blocking operation was interrupted by a call to WSACancelBlockingCall"))
                    return;
            }
        }
    }

    public abstract void handleGETRequest(SimpleHttpProcessor p);
    public abstract void handlePOSTRequest(SimpleHttpProcessor p, StreamReader inputData);
}

然后在关机时包含以下内容:

        simpleHttpServer.Listener.Server.Close();
        if (!thread.Join(10000)) // try to wait for it...
            thread.Abort();
        simpleHttpServer = null;

希望这对我在同一搜索中的另一个人有所帮助。这比预期的要长。

0 个答案:

没有答案