Hi,
Thanks for reading this!
For the people who never read any of my posts I am trying to write a proxy server in c#.
I am trying to "keep it simple" and stay away from asynchronous requests, but is not possible to totally avoid threading and I think I am encountering some multi threading problems.
The idea is to have a listener socket, binded to a certain prefix. Whatever requests I get there, I append them the correct credentials and send them straight to the (atuthenticated) server on the other side; then I grabb the bytes of the response and show them in the browser. For this I am using the HttpListenerContext class.
//TRANSFER DATA FROM REQUEST STREAM TO RESPONSE STREAM
// Close streams
instream.Close();
outstream.Close();
context.Response.OutputStream.Close();
}
catch (Exception ex)
{
}
}
catch
{
Restart();
}
}
Normally, everything goes ok; however, whenever I have a client that does a lot of requests very quickly (almost parallely) there is a problem in line writing the output stream (with the bytes that I just grabbed from the server) and an error is thrown:
An operation was attempted on a nonexistent network connection
This is misterious; is the network connection referring to the incoming stream (the server that I am comunicating with)? if its there is no apparent problem, because I checked and the connection is still on... or is this connection referring to the output stream? if it is, there is also no apparent problem cause I checked it with the functon CanWrite and it returns true, so it is looks in good health;
If anybody has any "light" to to bring into this question I would really appreciate it, cause I googled it to exhaustion and did not come to any conclusions :pirate: :v:
Anyway, moving on: I caught the error and figure out that I need to somehow close the streams that are opened; I did not find a clean easy way to do it (cause I cannot access the streams anymore), so the "brute-force" approach was to close the actual listener and start it again (so that I can again listen for connections);
Code:
private void Restart()
{
Stop();
Start();
}
Most of the times, this is ok, but sometimes, when I enter the Start() function, there is a problem with this line:
The I/O operation has been aborted because of either a thread exit or an application request
and then I am in a bit of a mess.
Apart from trying to solve this particular errors that cause my application to fail requests once in a while, I am looking at the bigger picture and wondering if the issues I am encountering are from not approaching properly the situation; am I having simultaneous access to the code and no handling properly the multithreading (I actually tried a lock() of the critical section without any improvement...) ? do I need multithreading here? or is it something else?
As I said, any help here would be much appreciated! Thanks in advance :^:
November 13th, 2009, 10:29 AM
doublebyte
Re: Threaded Proxy?
So I think the summary of the situation concerning multithreading in C# is (correct me if I'm wrong):
- use asynchronous requests and let the system handle the multithreading; (1)
- use threadPool and let the system handle the multitreading (distribute tasks among worker threads); (2)
- implement "real" multi threading, handling synchronization, locks, etc; (3)
I wanted to keep it as simple as possible, without having to write a lot of "thread" of code (unless absolutely necessary), so I tried to stick to option (2), which as Luc Pattyn mentioned, has some limitations but I think I can "live" with them (that is, the app fails sometimes, I can catch the errors and carry on without major implications for the user).
One thing that I amended in my code, was removing the "restart" of the listener on the event of an exception; there is no need to stop and start the listener on error, and in fact, when I had a lot of threads running, the "restart" of the listener itself was a cause of problems...
The I/O operation has been aborted because of either a thread exit or an application request
So, after refactoring my "ProcessRequest" callback, it now looks like this: no restart of the listener and separate handling of different types of exceptions; one important thing is to close the Context.Response after an error, so that it sends a response to the client;
context.Response.Close();
}
catch (Exception ex) { }//Default
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
// It should not come here! Are we having troubles closing the stream?
}
}
It's not the best solution, has it fails to deliver some jobs (not properly handling the multithreading), but its kind of working and is simple.
cheers,
Jo