erizet / ServerSentEvent4Net

Server-Sent Event(SSE) implementation for ASP.NET WebApi.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

启用心跳后连接断开导致程序崩溃

bjzycx opened this issue · comments

表现:启用心跳,一段时间后,断开客户端。然后程序会在不存在的连接上试图发送心跳,因为缺少了异常的捕获,导致服务端崩溃,
异常如下:
System.IO.IOException ---> System.Net.HttpListenerException: 企图在不存在的网络连接上进行操作。
在 System.Net.HttpResponseStream.Write(Byte[] buffer, Int32 offset, Int32 size)
在 Microsoft.Owin.Host.HttpListener.RequestProcessing.ExceptionFilterStream.Write(Byte[] buffer, Int32 offset, Int32 count)
--- 内部异常堆栈跟踪的结尾 ---
在 Microsoft.Owin.Host.HttpListener.RequestProcessing.ExceptionFilterStream.Write(Byte[] buffer, Int32 offset, Int32 count)
在 System.Net.Http.Internal.DelegatingStream.Write(Byte[] buffer, Int32 offset, Int32 count)
在 System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
在 System.IO.StreamWriter.Flush()
在 ServerSentEvent4Net.ServerSentEvent.Client.Send(IMessage msg) 位置 D:\Code\TFS2012\QinQouShui\QouShui\QProtocol\ServerSentEvent4Net\ServerSentEvent.cs:行号 240
在 ServerSentEvent4Net.ServerSentEvent.<>c__DisplayClass24_0.b__0(Client c) 位置 D:\Code\TFS2012\QinQouShui\QouShui\QProtocol\ServerSentEvent4Net\ServerSentEvent.cs:行号 120
在 System.Collections.Generic.List1.ForEach(Action1 action)
在 ServerSentEvent4Net.ServerSentEvent.SendAndRemoveDisconneced(List`1 clientsToSendTo, Message msg) 位置 D:\Code\TFS2012\QinQouShui\QouShui\QProtocol\ServerSentEvent4Net\ServerSentEvent.cs:行号 120
在 ServerSentEvent4Net.ServerSentEvent.Send(Message msg) 位置 D:\Code\TFS2012\QinQouShui\QouShui\QProtocol\ServerSentEvent4Net\ServerSentEvent.cs:行号 108

修正方法:增加通用异常捕获,修正后的代码如下:
` public void Send(IMessage msg)
{
try
{
// Only send retry once for each connection
if (IsRetrySent)
msg.Retry = null;

                var text = msg.ToString();
                StreamWriter.WriteLine(text);
                StreamWriter.Flush();

                if (!Message.IsOnlyComment(msg))
                    LastMessageId = msg.Id;

                if (!string.IsNullOrWhiteSpace(msg.Retry))
                    IsRetrySent = true;
            }
            catch (HttpException ex)
            {
                if (ex.ErrorCode == -2147023667) // The remote host closed the connection. 
                {
                    IsConnected = false;
                }
            }
            catch (System.ServiceModel.CommunicationException)
            {
                IsConnected = false;
            }
            **catch (IOException ex)
            {
                //IO异常,可判定为已断开
                IsConnected = false;
                Console.WriteLine("SSE Send Error:" + GetErr(ex));
            }
            catch (Exception ex)
            {
                Console.WriteLine("SSE Send Error:" + GetErr(ex));
            }**
        }

        string GetErr(Exception ex)
        {
            Exception innerException = ex.InnerException;
            string err = ex.Message;
            while (innerException != null)
            {
                err = innerException.Message;
                innerException = innerException.InnerException;
            }
            return err;
        }`