невозможно подключиться к удаленному серверу при использовании HttpWebRequest.GetRequestStream

Я создаю простое клиент-серверное HTTP-приложение на своем локальном компьютере, но я не знаю, почему ListenerCallback запускается на сервере; однако EndGetContext не завершается, выдавая «Веб-исключение: невозможно подключиться для удаления сервера» на стороне клиента. Есть идеи? вот код

    class Server
{
    static void Main(string[] args)
    {
        NonblockingListener(new string[] {"http://192.168.0.55:5432/"});
    }

    public static void NonblockingListener(string[] prefixes)
    {
        HttpListener listener = new HttpListener();
        foreach (string s in prefixes)
        {
            listener.Prefixes.Add(s);
        }
        listener.Start();
        IAsyncResult result = listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener);     
        Console.WriteLine("Waiting for request to be processed asyncronously.");
        result.AsyncWaitHandle.WaitOne();
        Console.WriteLine("Request processed asyncronously.");
        listener.Close();
    }

    public static void ListenerCallback(IAsyncResult result)
    {
        HttpListener listener = (HttpListener)result.AsyncState;
        // Call EndGetContext to complete the asynchronous operation.

        HttpListenerContext context = listener.EndGetContext(result);
        HttpListenerRequest request = context.Request;
        Stream reader = request.InputStream;


        HttpListenerResponse response = context.Response;

        string responseString = "<HTML><BODY> Hello World!</BODY></HTML>";
        byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);

        response.ContentLength64 = buffer.Length;
        System.IO.Stream output = response.OutputStream;
        output.Write(buffer, 0, buffer.Length);

        output.Close();
    }


}


   class Client
{
    public static void Main()
    {
        // Create a request using a URL that can receive a post. 
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://192.168.0.55:5432");

        request.UserAgent = "linkToShare - HTTPWebRequest";
        request.Method = "POST";
        // Create POST data and convert it to a byte array.
        string postData = "data data data data.";
        byte[] byteArray = Encoding.UTF8.GetBytes(postData);
        request.ContentType = "application/x-www-form-urlencoded";
        request.ContentLength = byteArray.Length;          
        Stream dataStream = request.GetRequestStream();
        dataStream.Write(byteArray, 0, byteArray.Length);
        dataStream.Close();
        WebResponse response = request.GetResponse();
        Console.WriteLine(((HttpWebResponse)response).StatusDescription);
        dataStream = response.GetResponseStream();
        StreamReader reader = new StreamReader(dataStream);
        string responseFromServer = reader.ReadToEnd();
        Console.WriteLine(responseFromServer);
        reader.Close();
        dataStream.Close();
        response.Close();
    }

}

person mustafabar    schedule 24.10.2010    source источник


Ответы (1)


Проблема с вашим кодом заключается в том, что на сервере вы вызываете метод EndGetContext, который установит WaitHandle и немедленно закроет сервер, прежде чем он успеет отправить ответ.

Вот небольшая модификация вашего кода.

Сервер:

class Program
{
    private static ManualResetEvent _waitHandle = new ManualResetEvent(false);

    static void Main()
    {
        NonblockingListener(new string[] { "http://+:5432/" });
    }

    public static void NonblockingListener(string[] prefixes)
    {
        using (var listener = new HttpListener())
        {
            foreach (string s in prefixes)
            {
                listener.Prefixes.Add(s);
            }
            listener.Start();
            var result = listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener);
            Console.WriteLine("Waiting for request to be processed asyncronously.");

            // Block here until the handle is Set in the callback
            _waitHandle.WaitOne();
            Console.WriteLine("Request processed asyncronously.");
            listener.Close();
        }
    }

    public static void ListenerCallback(IAsyncResult result)
    {
        var listener = (HttpListener)result.AsyncState;
        var context = listener.EndGetContext(result);

        var response = context.Response;
        string responseString = "<HTML><BODY>Hello World!</BODY></HTML>";
        byte[] buffer = Encoding.UTF8.GetBytes(responseString);
        response.ContentLength64 = buffer.Length;
        response.OutputStream.Write(buffer, 0, buffer.Length);
        // Finished sending the response, now set the wait handle
        _waitHandle.Set();
    }
}

Клиент:

class Program
{
    static void Main(string[] args)
    {
        using (var client = new WebClient())
        {
            client.Headers[HttpRequestHeader.UserAgent] = "linkToShare - HTTPWebRequest";
            var valuesToPost = new NameValueCollection
            {
                { "param1", "value1" },
                { "param2", "value2" },
            };
            var result = client.UploadValues("http://127.0.0.1:5432", valuesToPost);
            Console.WriteLine(Encoding.UTF8.GetString(result));
        }
    }
}
person Darin Dimitrov    schedule 24.10.2010
comment
Я скопировал ваш точный код на обеих сторонах клиента/сервера. client.UploadValues ​​дал мне это WebException {Невозможно записать данные в транспортное соединение: существующее соединение было принудительно закрыто удаленным хостом.} - person mustafabar; 24.10.2010
comment
Сервер выдает исключение? Посмотрите также журналы событий. - person Darin Dimitrov; 24.10.2010
comment
Я заметил, что сервер все еще закрывается до того, как клиент переходит к UploadValues. - person mustafabar; 24.10.2010
comment
Хм, это странно. Этого не происходит, когда я тестировал. _waitHandle инициализируется значением false, что означает, что если кто-то не вызовет для него .Set(), он будет заблокирован, и мы вызываем .Set() в конце метода ListenerCallback. - person Darin Dimitrov; 24.10.2010
comment
Я думаю, что решил это. Я просто удалил listener.close со стороны сервера и оставил GetContext внутри некоторое время (true), чтобы постоянно получать запросы - person mustafabar; 24.10.2010