I'm constantly getting the following exception which is caused by a user initiating a download and it consequently failing (or being cancelled):
Error Message : The remote host closed
the connection. The error code is
0x80072746. Stack Trace : at
System.Web.Hosting.ISAPIWorkerRequestInProcForIIS6.FlushCore(Byte[]
status, Byte[] header, Int32
keepConnected, Int32 totalBodySize,
Int32 numBodyFragments, IntPtr[]
bodyFragments, Int32[]
bodyFragmentLengths, Int32
doneWithSession, Int32 finalStatus,
Boolean& async) at
System.Web.Hosting.ISAPIWorkerRequest.FlushCachedResponse(Boolean
isFinal) at
System.Web.Hosting.ISAPIWorkerRequest.FlushResponse(Boolean
finalFlush) at
I've searched all over the internet, and found an interesting article, however there doesn't seem to be a definitive answer as the best way to prevent this filling up the logs.
The user sees no error and there's no actual problem in the app as it occurs only (to my understanding) in situations out of its control (user cancelling download or loss of connection) but there has to be a way to prevent such an exception being reported.
I hate to say it but I'm tempted to check for this exception and empty catch block its ass away - but this makes me feel like a dirty programmer.
So - what is the accepted method of preventing this exception filling up my mailbox?
The error occurs when you try to send a response to the client but they have disconnected. You can verify this by setting a breakpoint on the Response.Redirect or wherever you are sending data to the client, wait for Visual Studio to hit the breakpoint, then cancel the request in IE (using the x in the location bar). This should cause the error to occur.
To capture the error you can use the following:
try
{
Response.Redirect("~/SomePage.aspx");
Response.End();
}
catch (System.Threading.ThreadAbortException)
{
// Do nothing. This will happen normally after the redirect.
}
catch (System.Web.HttpException ex)
{
if (ex.ErrorCode == unchecked((int)0x80070057)) //Error Code = -2147024809
{
// Do nothing. This will happen if browser closes connection.
}
else
{
throw ex;
}
}
Or in C# 6 you can use Exception filters to prevent having to re throw the error:
try
{
Response.Redirect("~/SomePage.aspx");
Response.End();
}
catch (System.Threading.ThreadAbortException)
{
// Do nothing. This will happen normally after the redirect.
}
catch (System.Web.HttpException ex) when (ex.ErrorCode == unchecked((int)0x80070057))
{
// Do nothing. This will happen if browser closes connection.
}
Which is a better debugging experience since it will stop on the statement throwing the exception with the current state and all local variables preserved instead of on the throw inside the catch block.
You cannot prevent a remote Host to close anything.
And in some protocols this is the normal (or at least accepted) way to say goodbye.
So you will have to handle this specific exception.
From a practical perspective, there is nothing wrong with cancelling a download by virtue of a dead computer or a killed web session, therefore catching remote host closed exceptions is perfectly acceptable.
Related
I am creating a server for a game that deals with lots of TCP connections, and I need to deal with a sudden loss of connection (pc crash, game process killed, internet connection lost, ectect). The problem I currently have is that I can't tell apart a read error from a write error since both throw an IOException. even the underlying exception is the same (SocketException), the only difference being that one occurs on Socket.Send() and the other on Socket.Receive() respectively. I could of course compare the exception message, but that would become a problem as soon as the system language changes (and lets be honest, that would be a pretty messy approach anyway).
I tried comparing the Hresult but since the underlying exception is the same, so is the Hresult. I also tried getHashCode() but this one changes from player to player.
Any other ways I could tell apart those 2 situations?
To clarify, we're talking about the exception that comes up when using TcpClient.read() or TcpClient.write() on a TcpClient whose connection has been unexpectedly closed.
You could try wrapping the send and receive functions in a try-catch block, and use the Data property to tell exceptions from read and write apart:
enum ReadOrWrite { Read, Write }
void Foo()
{
try
{
socket.Receive();
}
catch (IOException ex)
{
ex.Data.Add("readOrWrite", ReadOrWrite.Read);
throw;
}
}
And this is where you later catch it:
try
{
Foo();
}
catch (IOException ex) when (ex.Data.Contains("readOrWrite"))
{
var readOrWrite = ex.Data["readOrWrite"];
}
The ASP.NET Core application uses websocket connection on the client side and Microsoft.AspNetCore.WebSockets.Server 0.1.0 (latest stable version on nuget as I know) on the server side. The simple sending code is
await _ws.SendAsync(new ArraySegment<byte>(arrbr), WebSocketMessageType.Text, true, ctk);
the problem is this line throws error when it is a closed connection. I would like that method to return a Boolean if process was successful. I already check if the connection is open like this:
_ws.State == WebSocketState.Open
But this does not work if user has
unplugged the network cable or disconnected his device(almost all situations except closing the browsers).
As an extra, I do not know how to simulate network connection loss for one of two clients and I suppose WebSocketState is readonly, please warn me if I am wrong and I do not think shorter pings will solve this problem.
I have two ideas:
I may use the sender code in a try catch block. (I am not comfortable with using try catch in production code)
I may set interval on the client side, and ask the server like "what is new for me". I feel bad with this because it is away from being a websocket(closer to http).
Is there any way to fix this without using try catch? I know that this is not a qualified question but a qualified problem for me. I can share full code if needed.
Update 1
after using server-side logging:
While messaging is working well in production environment, I disconnect the client by unplugging the network cable and send data to the client. I use try catch and no catch. then i get this error.
This means I cant detect lost connection by using try catch. and i think i can solve this by handling this throw.
How can I handle this error?
update2
I have noticed that "Exceptions from an Async Void Method Can’t Be Caught with Catch" and "it's possible to use await in catch" since c# 6 link however I can not catch the throw. I may try running synchronously await _ws.SendAsync(new ArraySegment<byte>(arrbr), WebSocketMessageType.Text, true, ctk).runsynchronously(); if I cant fix in this way
update3
running synchronously does not help. using try catch does not differ. as a result question, asp.net core websocket how to ping
update4
my log file when using Microsoft.aspnetcore.websockets.server 0.1.0
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HL1940BSEV8O": An unhandled exception was thrown by the application.
System.IO.IOException: Unexpected end of stream
at Microsoft.AspNetCore.WebSockets.Protocol.CommonWebSocket.<EnsureDataAvailableOrReadAsync>d__38.MoveNext()
my log file when using Microsoft.aspnetcore.websockets 1.0.0
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HL19H5R4CS21": An unhandled exception was thrown by the application.
System.Net.WebSockets.WebSocketException (0x80004005): The remote party closed the WebSocket connection without completing the close handshake. ---> System.IO.IOException: Error -4077 ECONNRESET connection reset by peer ---> Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException: Error -4077 ECONNRESET connection reset by peer
I might be missing something, but why can't wrap the sending operation in a method that returns bool in the following manner:
private async Task<bool> DoSend()
{
bool success = true;
try
{
await _ws.SendAsync(new ArraySegment<byte>(arrbr), WebSocketMessageType.Text, true, ctk);
}
catch (Exception ex)
{
// Do some logging with ex
success = false;
}
return success;
}
I also suggest reading about Async All The Way, it should clear some of the confusion with async void, async Task and async Task<T>
Until C# 6.0 to capture an exceptions from async methods you should use the ExceptionDispatchInfo type. Then the code will look like this:
private async Task<bool> DoSend()
{
bool success = true;
ExceptionDispatchInfo capturedException = null;
try
{
await _ws.SendAsync(new ArraySegment<byte>(arrbr), WebSocketMessageType.Text, true, ctk);
}
catch (Exception ex)
{
capturedException = ExceptionDispatchInfo.Capture(ex);
}
if (capturedException != null)
{
await ExceptionHandler();
if (needsThrow)
{
capturedException.Throw();
}
}
success = capturedException == null;
return success;
}
I have a confusing problem and I could not any way to workaround it. I have a couple of lines of codes, and at some point, the Send function throws a System.Net.Sockets.SocketException. However, even though try has the catch block, it does not catches the exception and continue with normal flow. When I try to run the case where it needs to throw same exception, catch captures it pretty well.
Things I have tried:
Trying to change VS debugging settings 'Enable Only For My Code', but
it is already disabled.
I tried to both Debug and Release modes.
I tried using general Exception catcher, but none of them worked.
Here is the code, at some point, the connection from the server closes and the c Socket disconnects. It returns the System.Net.Sockets.SocketException, but below catch does not capture it.
try
{
// Some code here . . .
c.Send(clientData);
Print("Started uploading the file " + uploadFilename + ".");
upBox.Text = "";
Print("Finished uploading the file " + uploadFilename + ".");
}
catch (System.Net.Sockets.SocketException)
{
Print("You are disconnected from server!");
}
The reason you're not getting an exception ...
... is that no exception has occurred!
TCP/IP itself won't necessarily "notice" a disconnect ... unless you explicitly try to write to a closed socket.
Definitely check out Beej's Guide to Network Programming:
http://www.beej.us/guide/bgnet/.
See also:
http://stefan.buettcher.org/cs/conn_closed.html,
How to detect a TCP socket disconnection (with C Berkeley socket)
I'm learning netcode and multithreading in Monodevelop, using C# with GTK#. I've never done either before, and now I find myself needing to do both at once.
I've used a tutorial chat program that has no error handling, and I've caught an error that happens in the client every single time I disconnect from the server. The code that sits in a thread listening for messages is as follows, surrounded by try/catch statements:
try
{
while (Connected)
{
if (!srReceiver.EndOfStream && Connected)
{
string temp = srReceiver.ReadLine();
// Show the messages in the log TextBox
Gtk.Application.Invoke(delegate
{
UpdateLog(temp);
});
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
After which the function finishes and the thread ends.
The code that ends the connection looks like this, and runs on the main thread:
private void CloseConnection(string Reason)
{
// Show the reason why the connection is ending
UpdateLog(Reason);
// Enable and disable the appropriate controls on the form
txtIp.Sensitive = true;
txtUser.Sensitive = true;
txtMessage.Sensitive = false;
btnSend.Sensitive = false;
btnConnect.Label = "Connect";
// Close the objects
Connected = false;
swSender.Close();
srReceiver.Close();
tcpServer.Close();
}
And the try/catch statements above catch this error:
System.IO.IOException: Unable to read data from the transport
connection: A blocking operation was interrupted by a call to
WSACancelBlockingCall. ---> System.Net.Sockets.SocketException: A
blocking operation was interrupted by a call to WSACancelBlockingCall
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset,
Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32
offset, Int32 size)
--- End of inner exception stack trace ---
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32
offset, Int32 size)
at System.IO.StreamReader.ReadBuffer()
at System.IO.StreamReader.get_EndOfStream()
at ChatClientGTK.MainWindow.ReceiveMessages() in
g:\Android\Tutes\ChatClientRemake\ChatClientGTK\MainWindow.cs:line 157
Now, as far as I can tell, when srReciever.Close() happens in the main thread, srReciever.ReadLine() is still trying to execute in the listening thread, which is where the problem lies, but even when I comment out srReciever.Close(), I still get the error.
As far as I can tell, there are no side-effects caused by just catching the error and moving on, but that doesn't really sit right with me. Do I need to fix this error, and if so, does anyone have any ideas?
Instead of using a ReadLine, can't you just do a Read and build up the String until a CrLf is detected then output that to update log.
ReadLine is a blocking call meaning it will sit there and always error if the connection is closed.
Otherwise you could just ignore the error. I know what you mean when you say it doesn't sit right but unless anyone else can enlighten me, I don't see that there is any leak in resources due to it and if it is an expected error then you can handle it appropriately.
Also I would probably catch the specific exception
catch (IOException ex)
{
Console.WriteLine(ex.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
The error is fine. If you really want it to go away, you can include a "bye" command in your protocol. So, if the server decides to disconnect, right before disconnecting he sends a "bye" to the client, so the client disconnects too, and most chances are that the exception will not be thrown. But you should still be prepared to catch it if it ever gets thrown. And then ignore it.
I'm working on two apps that connect to eachother using TCP. At one point, one of them is trying to connect using a TcpClient, but the other app is not guaranteed to have started listening yet (using TcpListener).
My first attempt was this:
TcpClient c = null;
while (true)
{
try
{
c = new TcpClient();
c.NoDelay = true;
c.Connect( ip, port );
break;
}
catch (SocketException ex)
{
Console.WriteLine(string.Format("Could not connect to {0}:{1}, retrying...", ip, port));
Thread.Sleep( 500 );
}
}
However, the problem with this is that it relies on exception handling which is a bit of a nuisance for me, because I have VS set up to catch any thrown exceptions ("Debug -> Exceptions..." menu). So every time it tries to connect, it breaks into VS and I have to press continue.
The exception I get is:
No connection could be made because the target machine actively refused it 127.0.0.1:50000
I would imagine that there would be a way to check if a server is listening on a specific port without actually trying to connect to it. I understand that just checking wouldn't be enough anyway - the server could go down between the check and the connect attempt, but it would still be much better for me while I'm developing it.
Or something like this:
TcpClient tcpClient = new TcpClient();
while ( !tcpClient.TryConnect(....) )
{ Thread.Sleep(1000); }
Analogous to this:
if (bool.TryParse( "false" ))
{ ... }
I also tried using async methods (Begin/End Connect) and setting the timeout for the ManualResetEvent manually, but that didn't work either. I've scoured the internets but I haven't been able to find a solution to this problem, which is why I'm finally posting here :)
The problem being that VS is breaking on the Exception? You you can always have VS ignore a specific family of Exceptions.
In VS, in the Debug Menu, choose "Exceptions..." and in the dialog presented you can control this.
I was going to suggest not catching an exception, so before I suggested that I test it myself, and if you set it to throw all exceptions even if you don't throw an exception its all exceptions are still being thrown. I will have to agree with Shiv Kumar, either adjust your settings while you debug your application, or accept the limitations of what you are doing.
The reason bool.TryParse works is it verifys each and every character, similarly to how Int32.TryParse makes sure that each character in the string is 0-9 or any other valid numerical symbol.
You could of course write your own networking class and not throw an exception when the connection fails.
TryParse will not throw an exception, you must catch any exception that is thrown if you use bool.Parse by try{}catch{} otherwise if you attempt to parse something that is not a boolean value it will throw an unhandled exception. TryParse was added later in the history of .NET, Parse is more of the classic method, allowing the programmer to handle all unexpected input and to validate input before trying to parse the data.
I should add that TryParse will return false if its unable to parse the value at both the method's result is false and the out variable I do believe is false.This is at least the case with Int32
http://msdn.microsoft.com/en-us/library/system.boolean.tryparse.aspx
I guess the point of pointing out how TryParse and Parse works is that they are entirely different beasts compare to TcpClient. I suppose I should clarify that the basic validation process is similar, except one throws an exception and the other one doesn't and of course one returns what was actually parsed.