HttpListener Called twice - c#

I am using this code to implement Http Server:
public Server()
{
_httpListener = new HttpListener();
_httpListener.Prefixes.Add(Server.UriAddress);
StartServer();
}
public void StartServer()
{
_httpListener.Start();
while (_httpListener.IsListening)
ProcessRequest();
}
void ProcessRequest()
{
var result = _httpListener.BeginGetContext(ListenerCallback, _httpListener);
result.AsyncWaitHandle.WaitOne();
}
void ListenerCallback(IAsyncResult result)
{
HttpListenerContext context = _httpListener.EndGetContext(result);
HttpListenerRequest request = context.Request;
string url = request.RawUrl;
url = url.Substring(1, url.Length - 1);
HttpListenerResponse response = context.Response;
string responseString = url;
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();
}
And i have a problem that if i wrote this in the browser(It's an example and it's occur on every call):
http://localhost:8888/Hello%20World
the ListenerCallback method is called twice,any idea how to fix it?

An answer has been accepted already, but I think it may still be useful to other people subsequently.
By default, most browsers given a URL would make at least two calls. One call to the request URL and the other to favicon.ico.
So a check should be made in ListenerCallback like
HttpListenerContext context = _httpListener.EndGetContext(result);
HttpListenerRequest request = context.Request;
string url = request.RawUrl;
url = url.Substring(1);
if (url == "favicon.ico")
{
return;
}
//normal request handling code
I hope this helps someone.

If your website requires several calls to the server, it will be called several times. This happens when you hav pictures or anything else on you page.
Try to call the synchronous method _httpListener.GetContext() or synchronize your calls with a lock or Mutex.

I am not sure but I think I see what might be a problem with your code.
You are mixing two patterns of async handling
You release the main thread by waiting on the waithandle in the async result.
But I think that only signals that you can call endgetcontext, not that another thread can use the listener.
If you are using the callback pattern, you should release the main thread using a wait handle other than that provided in the asyncresult

Related

ManualResetEvent.set not getting fired in C#

I am working on Visual Web Express 2010.
I am trying to upload a file to server and block the calling function and release it once uploading is complete. However, the main thread never gets unblocked.
public partial class MainPage : UserControl
{
private FileStream fileStream;
private static String responseStr = "";
private static ManualResetEvent evt = new ManualResetEvent(false);
public MainPage()
{
InitializeComponent();
HtmlPage.RegisterScriptableObject("App", this);
}
public void sendPhoto()
{
uploadFile();
}
private void uploadFile()
{
uploadDataToServer(url);
evt.WaitOne();
postProcess();
}
public static void postProcess()
{
HtmlPage.Window.Invoke("postProcess2", responseStr);
}
void uploadDataToServer(String url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "multipart/form-data; boundary=---------------------------" + _boundaryNo;
request.Method = "POST";
request.BeginGetRequestStream(writeCallback, request);
}
private void writeCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
MemoryStream memoryStream = new MemoryStream();
fileStream.CopyTo(memoryStream);
if (memoryStream != null)
{
memoryStream.Position = 0;
byte[] img = memoryStream.ToArray();
Stream postStream = request.EndGetRequestStream(asynchronousResult);
postStream.Write(img, 0, img.Length);
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
}
private void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
streamRead.Close();
streamResponse.Close();
response.Close();
responseStr = responseString;
evt.Set();
}
}
Now, when I use evt.WaitOne() in uploadFile, the whole app goes waiting and no request is send to server, i.e. the code never reaches getResponseCallBack and hence the application never wakes up.
However, if I don't use evt.WaitOne(), then the request is successful, however I can't read the response text since it's set in writeCallBack() function and the request is async one. What should I do to get over this problem?
I can't figure out:
1. If the request is multi-threaded / Async, then why evt.WaitOne() makes the complete app waiting and the request doesn't complete?
2. If the request is single threaded, then why postProcess() [removing the evt.WaitOne()] on trying to access responseStr [set in the getResponseCallBack()] doesn't get the proper response set in it.
[Sorry, I am new to this and am confused].
Thanks.
Sorry, I forgot to mention one thing that, I am using silverlight.
There is no point in starting an async operation and then waiting for it to complete. Instead of async request.BeginGetRequestStream(writeCallback, request); use the synchronous request.GetRequestStream(...) and consume it's result. ManualResetEvent would not be needed then.
Here is the solution to the problem that I figured out:
Some have advised to use HttpWebRequest.GetRequestStream and make the call synchronous. However, as it seems that silverlight doesn't allow this to take place. Moreover, there was many confusion related to threading and parrallel-processing.
The main problem was that I wasn't able to access the UI thread from my callback function, so I used the dispatcher method and since it always makes sure that the actions are performed in UI thread, my objective got fulfilled. The following did the trick.
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() => { postProcess(); });

How to wait until the file is downloaded (or URL is validated)?

I have a problem, I want to wait in the Main() until the Download() is finished. However, the file downloading/checking starts, at the same time the other lines start executing.
How can I use awaitor anything else to wait in the Main?
private void Main()
{
Download("http://webserver/file.xml");
//Do something here ONLY if the file exists!!
}
//This method invokes the URL validation
private void Download(downloadURL)
{
System.Uri targetUri = new System.Uri(downloadURL);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(targetUri);
request.BeginGetResponse(new AsyncCallback(WebRequestCallBack), request);
}
//In this method the URL is being checked for its validity
void WebRequestCallBack(IAsyncResult result)
{
HttpWebRequest resultInfo = (HttpWebRequest)result.AsyncState;
HttpWebResponse response;
string statusCode;
try
{
response = (HttpWebResponse)resultInfo.EndGetResponse(result);
statusCode = response.StatusCode.ToString();
}
catch (WebException e)
{
statusCode = e.Message;
}
onCompletion(statusCode);
}
//This method does not help! I just added if it could be any useful
private void onCompletion(string status)
{
if (status == HttpStatusCode.OK.ToString())
MessageBox.Show("file exists");
else
MessageBox.Show("file does not exists");
}
What I need, in detail is...
Download a file from a given URL
Before downloading verify the URL
if (verfied) then
continue downloading and do other tasks
else
fail and stop the process, Don't download! and give a message that URL was broken (couldn't verified)!
I am trying to do the "Verification" part, checking if the URL is correct and waiting for response. I need some kind of STATUS of the verification process, in order to continue.
Should try:
var task = Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse,
request.EndGetResponse, null);
var response = task.Result;
You can use a ManualResetEventSlim object. Initialize it to true when you instantiate it. At the end of OnComplete method call the Reset method on the ManualResetEventSlim object. In your main application, you just have to invoke the WaitOne method on the ManualResetEventSlim object.

Simple Task-returning Asynchronous HtppListener with async/await and handling high load

I have created the following simple HttpListener to serve multiple requests at the same time (on .NET 4.5):
class Program {
static void Main(string[] args) {
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://+:8088/");
listener.Start();
ProcessAsync(listener).ContinueWith(task => { });
Console.ReadLine();
}
static async Task ProcessAsync(HttpListener listener) {
HttpListenerContext ctx = await listener.GetContextAsync();
// spin up another listener
Task.Factory.StartNew(() => ProcessAsync(listener));
// Simulate long running operation
Thread.Sleep(1000);
// Perform
Perform(ctx);
await ProcessAsync(listener);
}
static void Perform(HttpListenerContext ctx) {
HttpListenerResponse response = ctx.Response;
string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
// You must close the output stream.
output.Close();
}
}
I use Apache Benchmark Tool to load test this. When I make a 1 request, I get the max wait time for a request as 1 second. If I make 10 requests, for example, max wait time for a response goes up to 2 seconds.
How would you change my above code to make it as efficient as it can be?
Edit
After #JonSkeet's answer, I changed the code as below. Initially, I tried to simulate a blocking call but I guess it was the core problem. So,I took #JonSkeet's suggestion and change that to Task.Delay(1000). Now, the below code gives max. wait time as approx. 1 sec for 10 concurrent requests:
class Program {
static bool KeepGoing = true;
static List<Task> OngoingTasks = new List<Task>();
static void Main(string[] args) {
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://+:8088/");
listener.Start();
ProcessAsync(listener).ContinueWith(async task => {
await Task.WhenAll(OngoingTasks.ToArray());
});
var cmd = Console.ReadLine();
if (cmd.Equals("q", StringComparison.OrdinalIgnoreCase)) {
KeepGoing = false;
}
Console.ReadLine();
}
static async Task ProcessAsync(HttpListener listener) {
while (KeepGoing) {
HttpListenerContext context = await listener.GetContextAsync();
HandleRequestAsync(context);
// TODO: figure out the best way add ongoing tasks to OngoingTasks.
}
}
static async Task HandleRequestAsync(HttpListenerContext context) {
// Do processing here, possibly affecting KeepGoing to make the
// server shut down.
await Task.Delay(1000);
Perform(context);
}
static void Perform(HttpListenerContext ctx) {
HttpListenerResponse response = ctx.Response;
string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
// You must close the output stream.
output.Close();
}
}
It looks to me like you'll end up with a bifurcation of listeners. Within ProcessAsync, you start a new task to listen (via Task.Factory.StartNew), and then you call ProcessAsync again at the end of the method. How can that ever finish? It's not clear whether that's the cause of your performance problems, but it definitely looks like an issue in general.
I'd suggest changing your code to be just a simple loop:
static async Task ProcessAsync(HttpListener listener) {
while (KeepGoing) {
var context = await listener.GetContextAsync();
HandleRequestAsync(context);
}
}
static async Task HandleRequestAsync(HttpListenerContext context) {
// Do processing here, possibly affecting KeepGoing to make the
// server shut down.
}
Now currently the above code ignores the return value of HandleRequestAsync. You may want to keep a list of the "currently in flight" tasks, and when you've been asked to shut down, use await Task.WhenAll(inFlightTasks) to avoid bringing the server down too quickly.
Also note that Thread.Sleep is a blocking delay. An asynchronous delay would be await Task.Delay(1000).

C# httplistener begingetcontext wont call callback using msdn example

I'm basically running the example here:
http://msdn.microsoft.com/en-us/library/system.net.httplistener.begingetcontext.aspx
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
namespace Servertest
{
class Program
{
static string msg;
public static void Main(string[] prefixes)
{
if (!HttpListener.IsSupported)
{
Console.WriteLine("Windows XP SP2 or Server 2003 is required to use the HttpListener class.");
Console.ReadLine();
return;
}
// URI prefixes are required,
// for example "http://contoso.com:8080/index/".
//if (prefixes == null || prefixes.Length == 0)
// throw new ArgumentException("prefixes");
// Create a listener.
HttpListener listener = new HttpListener();
// Add the prefixes.
//foreach (string s in prefixes)
//{
listener.Prefixes.Add("http://*:2999/");
//}
listener.Start();
Console.WriteLine("Listening...");
// Note: The GetContext method blocks while waiting for a request.
IAsyncResult result = listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener);
// Applications can do some work here while waiting for the
// request. If no work can be done until you have processed a request,
// use a wait handle to prevent this thread from terminating
// while the asynchronous operation completes.
Console.WriteLine("Waiting for request to be processed asyncronously.");
result.AsyncWaitHandle.WaitOne();
Console.WriteLine("Request processed asyncronously.");
Console.WriteLine(msg);
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;
// Obtain a response object.
//Break point here doesnt even get stopped
//Console.WriteLine(request.RawUrl) doesn't show anything either
msg = new string(request.RawUrl.ToCharArray());
HttpListenerResponse response = context.Response;
// Construct a response.
string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
// You must close the output stream.
output.Close();
}
}
}
The RawUrl doesnt get printed, and msg is blank too. Break points I put in the callback function don't even stop the execution
Got it, the issue was the listener.Close() is the main function which was being executed right when WaitOne() returned so in the ListenerCallback it was saying the resource was already disposed of.
Also needed this at the end of the callback
IAsyncResult result = listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener);
to accept next request

HttpWebRequest.BeginGetRequestStream() best practice

I'm working on an async Http crawler that gathers data from various services, and at the moment, I'm working with threadpools that do serial HttpWebRequest calls to post/get data from the services.
I want to transition over to the async web calls (BeginGetRequestStream and BeginGetResponse), I need some way get the response data and POST stats (% completed with the write, when complete (when complete more important), etc). I currently have an event that is called from the object that spawns/contains the thread, signaling HTTP data has been received. Is there an event in the WebRequests I can attach to to call the already implemented event? That would be the most seamless for the transition.
Thanks for any help!!
The following code I just copy/pasted (and edited) from this article about asynchronous Web requests. It shows a basic pattern of how you can write asynchronous code in a somewhat organized fashion, while keeping track of what responses go with what requests, etc. When you're finished with the response, just fire an event that notifies the UI that a response finished.
private void ScanSites ()
{
// for each URL in the collection...
WebRequest request = HttpWebRequest.Create(uri);
// RequestState is a custom class to pass info
RequestState state = new RequestState(request, data);
IAsyncResult result = request.BeginGetResponse(
new AsyncCallback(UpdateItem),state);
}
private void UpdateItem (IAsyncResult result)
{
// grab the custom state object
RequestState state = (RequestState)result.AsyncState;
WebRequest request = (WebRequest)state.request;
// get the Response
HttpWebResponse response =
(HttpWebResponse )request.EndGetResponse(result);
// fire the event that notifies the UI that data has been retrieved...
}
Note you can replace the RequestState object with any sort of object you want that will help you keep track of things.
You are probably already doing this, but if not, I believe this is a perfectly acceptable and clean way to tackle the problem. If this isn't what you were looking for, let me know.
You could passing a delegate (as part of the async "state" parameter) that needs to be called. Then after your EndGetResponseStream do what you need and then call this delegate with any parameters you need.
Personally, since you're moving to the aysnc programming model (I assume to get better performance) I strongly suggest you move your workflow over to to asynchronous as well. This model allows you to process the results as they come in and as fast as possible without any blocking whatsoever.
Edit
On my blog there is an article
HttpWebRequest - Asynchronous Programming Model/Task.Factory.FromAsyc
on this subject. I'm currently in the process of writing it, but I've presented a class that I think you could use in your situation. Take a look at either the GetAsync method or PostAsync method depending on what you need.
public static void GetAsyncTask(string url, Action<HttpWebRequestCallbackState> responseCallback,
string contentType = "application/x-www-form-urlencoded")
Notice the responseCallback parameter? Well that's the delegate I talked about earlier.
Here is an example of how you'd call it (I'm showing the PostAsyn() method
var iterations = 100;
for (int i = 0; i < iterations; i++)
{
var postParameters = new NameValueCollection();
postParameters.Add("data", i.ToString());
HttpSocket.PostAsync(url, postParameters, callbackState =>
{
if (callbackState.Exception != null)
throw callbackState.Exception;
Console.WriteLine(HttpSocket.GetResponseText(callbackState.ResponseStream));
});
}
The loop could be your collection of urls. In the case of a GET you don't need to send any (POST) parameters and the callback is the lambda you see where I'm writing to the console. Here you could do what you need, of you could send in a delegate so the response processing is done "elsewhere".
Also the callback method is an
Action<HttpWebRequestCallbackState>
Where HttpWebRequestCallbackState is a custom class you can modify to include any information you need for your purposes. Or you could modify the signature to to an Action.
You can use the System.Net.WebClient class:
var client = new WebClient();
client.DownloadDataCompleted += (s, args) => { /* do stuff here */ };
client.DownloadDataAsync(new Uri("http://someuri.com/"));
The second method is my primary way of ending the response.
public string GetResponse()
{
// Get the original response.
var response = _request.GetResponse();
Status = ((HttpWebResponse) response).StatusDescription;
// Get the stream containing all content returned by the requested server.
_dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
var reader = new StreamReader(_dataStream);
// Read the content fully up to the end.
var responseFromServer = reader.ReadToEnd();
// Clean up the streams.
reader.Close();
if (_dataStream != null)
_dataStream.Close();
response.Close();
return responseFromServer;
}
/// <summary>
/// Custom timeout on responses
/// </summary>
/// <param name="millisec"></param>
/// <returns></returns>
public string GetResponse(int millisec)
{
//Spin off a new thread that's safe for an ASP.NET application pool.
var responseFromServer = "";
var resetEvent = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(arg =>
{
try
{
responseFromServer = GetResponse();
}
catch (Exception ex)
{
throw ex;
}
finally
{
resetEvent.Set();//end of thread
}
});
//handle a timeout with a asp.net thread safe method
WaitHandle.WaitAll(new WaitHandle[] { resetEvent }, millisec);
return responseFromServer;
}

Categories