Reputation: 336
Per the comments, and my own testing, I am certain that my initial TCP port is not clearing out, and I don't really know how to remedy it.
I tried to run through the prefixes like so within my refresh method:
foreach (string item in myWebListener.Prefixes) {
if (item.Contains("http://127.0.0.1:5000")) {
myWebListener.Prefixes.Remove(item);
}
}
This did not make any noticeable change in the behavior.
The only other thing that was popping up in the web logs was something about the favicon.ico file, and just maybe another browser thread is trapping my connection trying to retrieve this and was going to provide it as an async callback to finish things out, though I didn't provide it so this line of thinking makes sense to me (How to provide a favicon.ico file in my byte stream as an embedded resource is My next research project).
If this shows no changes, my next research project is trying to leverage TCPListener:
I ran across this Q/A, but it really didn't help me as I am not familiar with the TCP way of doing what I have done here, and the work-around looks similar to what I was already attempting in my original code.
There was a mention of a using statement in the linked Q/A, and my guess is that it would look something like:
using(TCPListener myTCPListener = new TCPListener()) {
//Set the necessary TCP statements here.
//Do what I already did with my existing code here.
}
That's as far as my brain can take me so far, does this sound far off based on the factors at play here?
BELOW WAS THE ORIGINAL QUESTION CONTENT:
I am successfully reaching my running C# HttpListener localhost server, and successfully sending information back out to the local requesting browser page.
But after the first time, I completely lock up the browser web page waiting for a new response.
I debug with no errors on VS, so I don't even know where to look next; Hence that's why I'm here.
My hope is, is that someone can shed some light on how to refresh my server internally, so when the new query is needed, I can respond to it just like it was the first time.
I'm using an http get method to call this, so the call would look similar to the following:
"http://127.0.0.1:5000/?param1=searchForThings¶m2=itemToSearchFor";
I have to rip out a lot of proprietary code, but here is what is happening:
public class myWebServer {
public myWebServer() {
refresh();
//The Global is being set When the API
// Loads & is referenced here
ev1 = _MyGlobalEvents.ev1
}
public static HttpListener myWebListener { get; set; }
public static HttpListenerContext context { get; set; }
public static AsyncCallback myGetCallback { get; set; }
public static HttpResponseMessage myResp { get; set; }
public static Stream output { get; set; }
public static MyAPIDefinedEventType ev1 { get; set; }
public static void refresh() {
if (myWebListener != null) {
myWebListener.Stop();
myWebListener.Close();
}
if (output != null) { output.Dispose(); }
if (myGetCallback != null) { myGetCallback = null; }
myWebListener = new HttpListener();
myGetCallback = new AsyncCallback(processRequest);
myWebListener.Prefixes.Add("http://127.0.0.1:5000/");
myWebListener.Start();
myResp = new HttpResponseMessage(HttpStatusCode.Created);
myWebListener.BeginGetContext(myGetCallback, myResp);
}
public static void processRequest(IAsyncResult result) {
context = myWebListener.EndGetContext(result);
context.Response.KeepAlive = true;
myResp = new HttpResponseMessage(HttpStatusCode.Accepted);
context.Response.StatusCode = (int)HttpStatusCode.Accepted;
output = context.Response.OutputStream;
string label = context.Request.QueryString["param1"];
string fiStr = context.Request.QueryString["param2"];
if (label != null || label != "" || label.Contains("\n") == false) {
int pass1 = 0;
int pass2 = 0;
try {
int myInt = label.ToCharArray().Length;
pass1 = 1;
} catch { }
if (pass1 > 0) {
try {
int myInt2 = fiStr.ToCharArray().Length;
pass2 = 1;
} catch { }
}
if ((pass1 == 1 && pass2 == 0) || (pass1 == 1 && pass2 == 1)) {
pass1 = 0;
pass2 = 0;
if (label == "searchForThings" && (fiStr != null && fiStr != "")) {
string respStr = "<html><body><div id=\"status_msg\" style=\"display:inline;\">" + fiStr + "</div></body></html>";
byte[] respBuffer = Encoding.ASCII.GetBytes(respStr);
context.Response.StatusCode = (int)HttpStatusCode.Accepted;
output.Write(respBuffer, 0, respBuffer.Length);
_MyGlobalEvents.searchStr = fiStr;
ev1.Raise();
}
}
}
}
//When the Custom Event is done processing it runs something like the
//following to clean up and finalize
public void _processSearch(string resultStr) { processSearch(resultStr); }
public static void processSearch(string resultStr) {
string respStr = "<html><head>" +
"<style type=\"text/css\">" +
"tr.dispRow{ display:table-row; }\n" +
"tr.noRow{ display:none; }" +
"</style>" +
"</head>" +
"<body>" +
resultStr +
"</body></html>";
byte[] respBuffer = Encoding.ASCII.GetBytes(respStr);
output.Flush();
context.Response.StatusCode = (int)HttpStatusCode.OK;
output.Write(respBuffer, 0, respBuffer.Length);
output.Close();
context.Response.KeepAlive = false;
context.Response.Close();
refresh();
}
}
public static class _MyGlobalEvents {
public static string searchStr { get; set; }
public static MyAPIDefinedEventType ev1 { get; set; }
}
Upvotes: 0
Views: 811
Reputation: 336
My particular problem was actually the favicon.ico file request from the browser locking up the connection.
Early on I was noticing that my server was being hit twice, and that is why I had my flags in place to make certain that I was only operating on what was the actual Get request based on the URL I was expecting...
Otherwise the URL was erroring as a blank string (turns out this was the favicon.ico request being made - irritating, because when the string is completely empty you have no idea how to troubleshoot it). So I was ignoring it and not touching what I didn't understand.
Well it turns I could NOT ignore this request, because the browser is expecting a response for it. All I had to do was put an else section in my code that executed if my flag options weren't met, and close, dispose and refresh the connection when this happened.
This Q/A really described the solidified solution to the problem fairly well, but my Exception.Message was blank which didn't really get addressed there either, so I'm glad I get to document it here in the hopes that anyone else who may ever run into the same problem finds the answer a little more strait forward.
As for the answer that PhillipH provided, this proved to be the most helpful to me, as it revealed to me that I needed to be checking what was happening from the network traffic eventing.
However I could not really use the tools that this user suggested, but found an alternative with Google Chrome's built in chrome://net-internals/. Just type that into your address bar in chrome and execute it.
Anyway way this was the total answer for me, but PhillipH you deserve it for moving me in the right direction.
Upvotes: 0
Reputation: 6202
"But after the first time, I completely lock up the browser web page waiting for a new response" - are you saying the error is seen on the browser sending an Http request but getting no response ?
I'd advise downloading and using Telerik Fiddler (free) to see whats actually being sent and received between the client and server.
As other respondees have said - this is not a normal pattern for HttpListener and I'd guess you are having problems with TCP port caching on the server, and your .Stop() and .Close() methods are not freeing the TCP port (Windows caches it)
Upvotes: 1