unable to connect to remote server when using HttpWebRequest.GetRequestStream - c#

I am creating a simple HTTP client/server application on my local machine but I don't know why the ListenerCallback is triggered on the server; however, EndGetContext is not completing while throwing 'Web Exception: Unable to connect to remove server" on the client side. Any ideas? here's the code
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();
}
}

The problem with your code is that in the server you are calling EndGetContext method which will set the WaitHandle and immediately close the server before it had any time to send the response.
Here's a slight modification of your code.
Server:
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();
}
}
Client:
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));
}
}
}

Related

HttpListener Conflicts with existing registration

I have created a function (ListenForJson) in which I am using HttpListener to get requests and send responses from/to a specific address. I am calling this function inside ActionResult Index() so that it can run in the background. However, since I am calling it in the Homepage of my Webapp, whenever I click on the "Go to Home" button I receive an error the error
Failed to listen on prefix because it conficts with an existing registration on the machine
I understand the reason it happens but I do not know how I can stop it from happening.
public ActionResult Index()
{
Thread thread = new Thread(() => ListenForJson());
thread.Start();
return View();
}
public void ListenForJson()
{
string[] prefixes = new string[] { "https://localhost:44337/" };
if (prefixes == null || prefixes.Length == 0)
throw new ArgumentException("prefixes");
HttpListener listener = new HttpListener();
foreach (string s in prefixes)
listener.Prefixes.Add(s);
listener.Start();
while (true)
{
HttpListenerContext context = listener.GetContext();
HttpListenerRequest request = context.Request;
//Get Body(Json)
System.IO.Stream body = request.InputStream;
System.Text.Encoding encoding = request.ContentEncoding;
System.IO.StreamReader reader = new System.IO.StreamReader(body, encoding);
string json = reader.ReadToEnd();
JsonObject = DeserializeJson(json);
HttpListenerResponse response = context.Response;
var responseJson = JsonSerialization("SERVICE");
byte[] buffer = new byte[] { };
response.ContentType = "Application/json";
buffer = Encoding.ASCII.GetBytes(responseJson);
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
context.Response.Close();
}
}

HttpListener not responding to https request

I've created a small app to get http/https responses:
public static void Listener1(string[] prefixes)
{
if (!HttpListener.IsSupported)
{
Console.WriteLine("Seu ambiente não suporta os recursos da classe HttpListener.");
return;
}
if (prefixes == null || prefixes.Length == 0)
throw new ArgumentException("prefixes");
HttpListener listener = new HttpListener();
foreach (string s in prefixes)
{
listener.Prefixes.Add(s);
}
listener.Start();
Console.WriteLine("Listening...");
HttpListenerContext context = listener.GetContext();
HttpListenerRequest request = context.Request;
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();
listener.Stop();
}
And I'm using this prefixes:
string[] url = { "http://localhost:5324/", "https://localhost:5325/" };
When I type http://localhost:5324/ on Chrome, I get the right response, but when using https://localhost:5325/, nothing happens. Not even errors about certificates.

Exception handling in Async callback .Net

I am making an async request, BeginGetRequestStream, where the callback handles the EndRequest. I would like to send any exceptions happening in the callback method ReadCallback(), back to the main calling method InsertSoapEnvelopeIntoWebRequest.
private void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml,
HttpWebRequest webRequest)
{
try
{
webRequest.ContentLength = soapEnvelopeXml.InnerXml.Length;
this.soapEnvelopeXml = soapEnvelopeXml;
allDone = new ManualResetEvent(false);
IAsyncResult r = (IAsyncResult)webRequest.BeginGetRequestStream(
new AsyncCallback(ReadCallback), webRequest);
allDone.WaitOne();
}
catch(Exception ex)
{
throw;
}
}
private void ReadCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest myRequestState = (HttpWebRequest)asynchronousResult.AsyncState;
byte[] byteArray = null;
using (Stream streamResponse =
myRequestState.EndGetRequestStream(asynchronousResult))
{
byteArray = Encoding.UTF8.GetBytes(soapEnvelopeXml.InnerXml);
streamResponse.Write(byteArray, 0, byteArray.Length);
}
allDone.Set();
}
How do I achieve this ?
Thanks,
Gagan

Push an variable into a method

I have an httpWebRequest to access an XML and save it locally then read it and show it to the screen. Problem is, i have to do this for more than one "pivot item", and the method that saves the xml is
private static void GetResponseCallback(IAsyncResult asynchronousResult)
and doesn't support adding a new variable to it so i can dynamically name the xml ("tmp"+xmlName+".xml") .
So the question is: How do i push a variable in the xml name ?
public class HttpWebReqMethod
{
public void httpRequestMethod (string url, string xmlName)
{
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url);
httpRequest.ContentType = "text/xml";
httpRequest.Method = "POST";
httpRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), httpRequest);
}
private static void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest httpRequest = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
Stream postStream = httpRequest.EndGetRequestStream(asynchronousResult);
string postData = "";
// Convert the string into a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Write to the request stream.
postStream.Write(byteArray, 0, postData.Length);
postStream.Close();
// Start the asynchronous operation to get the response
httpRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), httpRequest);
}
private static void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest httpRequest = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)httpRequest.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseStream = streamRead.ReadToEnd();
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var istream = new IsolatedStorageFileStream(#"tmp" + xmlName + ".xml", FileMode.OpenOrCreate, store))
{
using (var sw = new StreamWriter(istream))
{
sw.Write(responseStream);
}
}
}
// Close the stream object
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse
response.Close();
}
Here are two things you could do:
make GetResponseCallback not static, and store the xmlName in an instance variable
pass a state object (anything that has a property named xmlName, and something else to identify it by) to the request, and you can get it from the AsyncState
change GetResponseCallback's function to the following, and make the whole thing a callback "factory"
private static AsyncCallback GetResponseCallback(string xmlName)
{
return (IAsyncResult asynchronousResult) =>{
HttpWebRequest httpRequest = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)httpRequest.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseStream = streamRead.ReadToEnd();
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var istream = new IsolatedStorageFileStream(#"tmp" + xmlName + ".xml", FileMode.OpenOrCreate, store))
{
using (var sw = new StreamWriter(istream))
{
sw.Write(responseStream);
}
}
}
// Close the stream object
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse
response.Close();
}
}
EDIT to ADD:
the usage then changes to
httpRequest.BeginGetRequestStream(GetRequestStreamCallback(xmlName), httpRequest);
It's a callback method which is mapped to a specific delegate type, so no, you can't amend it's signature.
One option to resolve this would be to have a separate class such as this:
class HttpRequestState {
HttpWebRequest httpWebRequest;
string xmlFileName;
}
You can then set an instance of that class as the state object when you run the Begin callback:
httpRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), httpRequest);
would change to
httpRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), new HttpRequestState() { httpWebRequest = httpRequest; xmlFileName = "tmp"+xmlName+".xml" });
Then of course, you can pull out the xmlFileName and the httpWebRequest like this:
HttpRequestState stateObj = (HttpRequestState)asynchronousResult.AsyncState;
HttpWebRequest httpRequest = stateObj.httpWebRequest;
string fileName = xmlFileName;

WP7 app never exits BeginGetResponse and goes into the callback function

I have the following code:
private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
Stream postStream = request.EndGetRequestStream(asynchronousResult);
//Console.WriteLine("Please enter the input data to be posted:");
//string postData = Console.ReadLine();
string postData = "my data";
// Convert the string into a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Write to the request stream.
postStream.Write(byteArray, 0, postData.Length);
postStream.Close();
// Start the asynchronous operation to get the response
IAsyncResult result =
(IAsyncResult)request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
private void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
Console.WriteLine(responseString);
// Close the stream object
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse
response.Close();
allDone.Set();
Dispatcher.BeginInvoke((Action)(() => Debug.WriteLine("George")));
}
However when my code hits BeginGetResponse it never exits (and I do not hit a breakpoint in the GetResponseCallback function). I tried adding the BeginInvoke call, but I still never enter this method. This code works in a windows console app - it's on Windows Phone 7 that it doesn'teorg
Can anyone see what I am doing wrong?
Thanks.
If you have created the HttpWebRequest on the UI thread, then make sure you don't block the UI thread, otherwise you can deadlock.
The sample from the desktop .NET you have linked isn't optimized for the current phone networking stack. You should change the code so that you create the HttpWebRequest on a background thread.
I can't see what's wrong with your code (maybe a complete example of what you're trying to do may help) but here's a simple working example of a way of performing the action you want to do.
It posts some data to a URI and then passes the repsonse to a callback function:
Simply execute like this (use of a BackgroundWorker is not necessary but is recommended)
var bw = new BackgroundWorker();
bw.DoWork += (o, args) => PostDataToWebService("http://example.com/something", "key=value&key2=value2", MyCallback);
bw.RunWorkerAsync();
Here's the callback function it refers to:
(You can change this however is appropriate to your needs.)
public static void MyCallback(string aString, Exception e)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
if (e == null)
{
// aString is the response from the web server
MessageBox.Show(aString, "success", MessageBoxButton.OK);
}
else
{
MessageBox.Show(e.Message, "error", MessageBoxButton.OK);
}
});
}
Here's the actual method:
public void PostDataToWebService(string url, string data, Action<string, Exception> callback)
{
if (callback == null)
{
throw new Exception("callback may not be null");
}
try
{
var uri = new Uri(url, UriKind.Absolute);
var req = HttpWebRequest.CreateHttp(uri);
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
AsyncCallback GetTheResponse = ar =>
{
try
{
var result = ar.GetResponseAsString();
callback(result, null);
}
catch (Exception ex)
{
callback(null, ex);
}
};
AsyncCallback SetTheBodyOfTheRequest = ar =>
{
var request = ar.SetRequestBody(data);
request.BeginGetResponse(GetTheResponse, request);
};
req.BeginGetRequestStream(SetTheBodyOfTheRequest, req);
}
catch (Exception ex)
{
callback(null, ex);
}
}
and here are the extension/helper methods it uses:
public static class IAsyncResultExtensions
{
public static string GetResponseAsString(this IAsyncResult asyncResult)
{
string responseString;
var request = (HttpWebRequest)asyncResult.AsyncState;
using (var resp = (HttpWebResponse)request.EndGetResponse(asyncResult))
{
using (var streamResponse = resp.GetResponseStream())
{
using (var streamRead = new StreamReader(streamResponse))
{
responseString = streamRead.ReadToEnd();
}
}
}
return responseString;
}
public static HttpWebRequest SetRequestBody(this IAsyncResult asyncResult, string body)
{
var request = (HttpWebRequest)asyncResult.AsyncState;
using (var postStream = request.EndGetRequestStream(asyncResult))
{
using (var memStream = new MemoryStream())
{
var content = body;
var bytes = System.Text.Encoding.UTF8.GetBytes(content);
memStream.Write(bytes, 0, bytes.Length);
memStream.Position = 0;
var tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
postStream.Write(tempBuffer, 0, tempBuffer.Length);
}
}
return request;
}
}

Categories