Exception-proof HttpListener possible? - c#

Last few days I've been building a web server application in C# that uses HttpListener. I've learned quite a lot on the way, and still am. Currently I got it all working, setting headers here and there depending on certain situations.
In most cases things are working fine, however at times a exception error is thrown. This happens on a few occasions. Most if not all of them is closing a connection before all data is send. Then the error occurs. But some of them are really caused by browsers as far as I can tell.
Like let's take Chrome. Whenever I go to a MP3 file directly, it sends 2 GET requests. And one of them is causing the error, the other is working and receiving part of the content. After this, I can listen the MP3 and there are no issues. Streaming works.
But back to the request that gives me the error, there is nothing in the headers that I could use in my code to not output data, like I do already with HEAD requests. So I'm quite puzzled here.
IE also has this problem with both opening MP3 files directly, and streaming via HTML5 audio tag. It also varies from time to time. Sometimes I open the page, and only 2 requests are made. The HTML page, and the MP3. No error there. Sometimes tho, there are 3 requests. It connects to the MP3 twice. Now sometimes one of those connections is being aborted straight after I open the page, and sometimes 2 requests to the MP3 file, doesn't even accept data. In both request headers, they want end of the file. So bytes: 123-123/124.
I've also tested it on w3school's audio element. IE also makes twice connections there, one aborted, other loading the MP3 file.
So my question is, is it possible to make the web server exception/error-proof, or maybe better question, is it bad that these exceptions are thrown? Or do you perhaps know how to fix these errors?
The error I'm getting is: I/O Operation has been aborted by either a thread exit or an application request.
The way I write to the client is:
using (Stream Output = _CResponse.OutputStream)
{
Output.Write(_FileOutput, rangeBegin, rangeLength);
}
I am not sure if there's another (better) way. This is what I came across in many topics, tutorials and pages while researching.
About headers: Default headers: Content Length, Content Type, Status Code. In some cases, like MP3 files and video's, I add a Accept-Ranges: Bytes header. In case the request header has Range in it, I add Content-Range header, and PartialContent status code.

From the server's point of view any client can disconnect at any time. This is part of the normal operation of a server. Detect this specific case, log it and swallow the exception (because it has been handled). It's not a server bug.

Related

c# Socket send receive network

I'm totally confused and stunned about my problem. I wrote a multi client server using sockets.
I created a first GUI that receives clients and display them in a gridview, in the click gridview event it opens a new GUI with the socket between the clicked client and the server. So everything about the connection between server and the clients go well and fast
But my problems are :
the send information between them like sending full process it sometimes shown full and it sometimes less result .
send files management for example when the server request full folders/files in a directory sometimes it shows them all and sometimes less result .
But the command such open a window open an url, send a message , commands like those works so perfectly and instantly .
I am so confused right now what's the problem
Notice 1 : I used the extern IP for connection between server/client.
Notice 2 : internet connection is perfect (definitely not slow)
I tried to use different buffer sizes, but what I'm really confused about is that sometimes the result comes full with a specific buffer size and sometimes not with the same buffer size .
Thank you for your time !
I would also recommend you use wireshark so that you are able to get the full information and transactions that are really going on in the network.
This will help you to rule out where the issue is coming from.
To determine the packet size see the image
Here I am not talking about how the TCP handshaking protocol works as I assume it is working. However do note that in the transmission if you see something like RST then maybe somebody issued a reset command implying that some error occurred in the transmission. Such as something due to checksum for example. Although it is generally a problem for someone working directly on TCP/IP protocol
This should help you confirm that you sent and recieved the correct length.

How to implement file downloader to detect communication breakage?

I need to implement a file downloader in C#. This downloader will be running on the client computer, and will download several files according to several conditions.
The main restriction I have is that the client will probably go offline during downloading (sometime more than once), so I need the following things to happen:
1) Downloader should notice there isn’t any network communication anymore and pause downloading.
2) Downloader should resume downloading once communication is back, and continue collecting the packages, adding them to those that were already downloaded to the local disk.
I have checked StackOverflow previous posts and saw that there are two options – WebClient and WebRequest (using one of the inheritance classes). I was wondering if someone can advise which one to use based on the requirements I have specified. How can I detect communication breakage?
You will need System.Net.HttpWebRequest to send HTTP requests and System.IO.FileStream to access files. Two methods needed are HttpWebRequest.AddRange and Filestream.seek
HttpWebRequest.AddRange method adds a byte range header to the request, and the range parameter specifies the starting point of the range. The server will start sending data from the range parameter specified to the end of the data in the HTTP entity. While Filestream.seek method is used to access the current position within a stream.
Source and example
You need download resume (if supported by server you are downloading from) which means you should go with WebRequest since with WebClient you cannot do that (probably next versions will support RANGE requests).
As soon as connection is dropped your code which is reading network stream throws an exception. That tells you there is a problem with download (i.e. network problem) then you can try in some periods to make a new connection and if succeeded, resume from last successful byte (using RANGE in HTTP HEADER).

Fiddler makes HttpWebRequest/HttpClient behaviour unexpected

Just wanted to ask if somebody encountered a problem of using HttpWebRequest class (or even new HttpClient) when trying upload some file to the server when Fiddler is launched.
I have encountered the bug, namely, AllowWriteStreamBuffering property of HttpWebRequest class is not working when the fiddler is launched, so upload progress is not working at all. Bytes are not sent instantly but buffored even if I set AllowWriteStreamBuffering to true, therefore I can't track upload progress. It is works ok when fiddler is not launched.
Moreover if I close fiddler when my application is uploading some file, it will crash too throwing WebException which says "The underlying connection was closed: An unexpected error occurred on a receive."
The same things is happening with new .net 4.5 HttpClient class.
Sorry for the confusion; Fiddler currently only supports streaming of responses and not requests.
Some proxies (like Fiddler) or other intermediaries will fully buffer a request before sending it to the server for performance or functional (e.g. virus scanning, breakpoint debugging) reasons.
http://www.fiddler2.com/fiddler/help/streaming.asp
Ok, caught my interest this, it appears for AllowWriteSteamBuffering to work the server must support Chunked transfer encoding. which led me to this forum post about proxies and the afore mentioned chunked encoding: https://groups.google.com/forum/?fromgroups=#!topic/httpfiddler/UkOiK96kg_k.
It appears from what I read here that when using a proxy you may or may not get the chunked encoding, etc. hence your issue.
I also found this which seemed a good detailed article on uploading with feedback which may be helpful?
http://blogs.msdn.com/b/delay/archive/2009/09/08/when-framework-designers-outsmart-themselves-how-to-perform-streaming-http-uploads-with-net.aspx

Resume download of file in Silverlight 4 OOB

I have a Silverlight 4 out-of-browser application that needs to be able to resume the download of an external file if the download is interrupted for any reason. I would like to be able resume instead of restart from the beginning because the file will be rather large and we have the potential to have users on slower connections.
I found some code at,
http://www.codeproject.com/Tips/157532/Silverlight-4-OOB-HTTP-Download-Component-with-Pau.aspx
but there seems to be numerous errors in it, so I'm not exactly confident that I'll be able to get it to work.
So, if anyone has any other original suggestions or alternatives, I'd like to hear them.
Thanks,
One approach you might consider is managing the download using the HTTP/1.1 Acccept-Ranges response header and the Range request header.
Make sure the resource you are downloading will include the header:-
Accept-Ranges: bytes
when it is requested (a static file sent by IIS will do this by default).
Now using the ClientHTTP stack you make an initial "HEAD" request to determine the server will accept a Range: bytes= header in the request and find the total size of the content to be sent.
You then make a "GET" request for the resource including the header:-
Range: bytes=0-65535
This limits the downloaded content to just the first 64K chunk. You then repeat the same request with:-
Range: bytes=65536-131071
Each time you can save the content of the response stream to your destination file. You keep track of how many bytes you have received. When you determine the final chunk which is likely to less than full just use a header like:-
Range: bytes=131072-
That will read to the end of file.
If the requests to the server are fail you can resume at an appropriate point in this sequence.
You need to be degrade gracefully, if the server does not include the Accept-Ranges header in the initial "HEAD" request then you'll just have to download the whole file.

WebClient.UploadFile() throws exception on some binary files

I am using the WebClient.UploadFile() method to post files to a service for processing. The file contains an XML document with a compressed, b64-encoded content element in it. For some files (currently 1), the UploadFile throws an exception, indicating that the underlying connection was closed. The innermost exception on socket level gives the message 'An existing connection was forcibly closed by the remote host'.
Questions:
Has anyone necountered the same problem?
Why does it throw an exception for some files, and not for all?
Should I set some additional parameter for files with binary content?
Is there a workaround?
This functionality does work fine in a VPN situation, but obviously we want to use it to work in standard Internet situations.
Thanks, Rine
Sounds like a firewall or other security software sitting in between you and the server may be rejecting the request as a potential attack. I've run into this before where firewalls were rejecting requests that contained a specific file extension-- even if that file extension was encoded in a query string parameter!
If I were you, I'd take the problematic file and start trimming XML out of it. You may be able to find a specific chunk of XML which triggers the issue. Once you've identified the culprit, you can figure out how to get around the issue (e.g. by encoding those characters using their Unicode values instead of as text before sending the files). If, however, any change to the file causes the problem to go away (it's not caused by a specific piece of worrisome text), then I'm stumped.
Any chance it's a size issue and the problematic file is above a certain size and all the working files are below it? The server closing the connection when it hits a max accepted request size matches your symptom. You mentioned it worked in VPN so it's admittedly a stretch, but maybe the VPN case was a different server that's configured differently (or the max request is different for some other reason).
Are there non-WebClient methods for uploading the file to the same service from the same machine and if so, do they work?

Categories

Resources