【问题标题】:.net sockets ObjectDisposed exception.net 套接字 ObjectDisposed 异常
【发布时间】:2011-04-19 19:36:40
【问题描述】:

我在我的项目中使用异步套接字。

当我在我的类 NotifyConnection ObjecDispoded 中调用 Disconnect 方法时出现异常。 我意识到这是因为 socket.Close() 方法在内部调用了 Dispose。

有谁知道在这种情况下如何关闭套接字?

    public void Disconnect()
    {
        try
        {
            lock (_syncRoot)
            {                    
                _clientSocket.Shutdown(SocketShutdown.Both);
                _clientSocket.Close();
            }
        }
        catch (SocketException ex)
        {
            OnSocketExeceptionThrowed(new EventArgs<SocketException>(ex));
            NotificationAgentEm.LogExceptionToConsole(ex);
        }

    }

我希望没有调用 EndReceive,因为 socket.ShutDown 关闭套接字接收数据..但是在 socket.ShutDown;socket.Close 之后调用了 EndReceive。

抛出结束异常,因为此时套接字不存在。

   private void OnReceiveData(IAsyncResult ar)
    {
        try
        {
            TransferStateObject state = null;
            lock(_syncRoot)
            {
                string message;
                state = (TransferStateObject)ar.AsyncState;
                // in this place exception throwed . client socket not exist becaouse it destroyed in disconnect method
                int bytesRead = _clientSocket.EndReceive(ar);

了解我如何使用异步套接字。

   public void Connect(string host, int port)
    {
        if (host == null)
            throw new NullReferenceException();            
        try
        {
            _clientSocket = new Socket(AddressFamily.InterNetwork,
                                   SocketType.Stream, ProtocolType.Tcp);
            _clientSocket.Connect(host, port);
        }
        catch (Exception ex)
        {
            NotificationAgentEm.LogExceptionToConsole(ex);
            throw;
        }
    }
   public void Disconnect()
    {
        try
        {
            lock (_syncRoot)
            {                    
                _clientSocket.Shutdown(SocketShutdown.Both);
                _clientSocket.Close();
            }
        }
        catch (SocketException ex)
        {
            OnSocketExeceptionThrowed(new EventArgs<SocketException>(ex));
            NotificationAgentEm.LogExceptionToConsole(ex);
        }

    }
       public void StartListen()
    {
        if (_clientSocket == null)
        {
            throw new InvalidOperationException("No connection");
        }
        try
        {
            BeginReceive();
        }
        catch (SocketException ex)
        {              
            NotificationAgentEm.LogExceptionToConsole(ex);
            OnSocketExeceptionThrowed(new EventArgs<SocketException>(ex));
        }
    }  

  private void BeginReceive()
    {
        try
        {
            var receivedTranferObject = new TransferStateObject();
            _clientSocket.BeginReceive(
                receivedTranferObject.Buffer,
                0,
                TransferStateObject.BufferSize,
                0,
                new AsyncCallback(OnReceiveData),
                receivedTranferObject);
        }
        catch(SocketException ex)
        {
            OnSocketExeceptionThrowed(new EventArgs<SocketException>(ex));
            NotificationAgentEm.LogExceptionToConsole(ex);
        }
    }
  private void OnReceiveData(IAsyncResult ar)
    {
        try
        {
            TransferStateObject state = null;
            lock(_syncRoot)
            {
                string message;
                state = (TransferStateObject)ar.AsyncState;
                // in this place exception throwed . client socket not exist becaouse it    destroyed in disconnect method
                int bytesRead = _clientSocket.EndReceive(ar);
                 //bla bla bla
             }
         }

p.s 对不起我的英语

【问题讨论】:

  • 据我所知,您不必关闭连接。
  • 很难说问题出在哪里,你需要给我们更多关于'主循环'的细节
  • 如果您认为在接收数据的同时调用了 Disconnect,请检查您的程序逻辑。您还可以在 Disconnect 中设置一个断点,然后查看呼叫的来源。

标签: .net sockets


【解决方案1】:

不管我上面的评论如何,我都会重组 Disconnect 方法:

try
{
  lock (_syncRoot)
  {                    
      if ( null != _clientSocket )
      {
           _clientSocket.Shutdown(SocketShutdown.Both);
           _clientSocket.Close();
           _clientSocket = null;
       }
   }
}
catch (SocketException ex)
...

所以你不会再次关闭/关闭套接字。

但同样,为了真正帮助您,我们需要有关主要工作流程的更多详细信息。

PS:我确实知道将 if 放在锁内的惩罚,但我想保持简单,

马里奥

编辑:我在 cmets 部分讨论后添加了该功能:

private void OnReceiveData(IAsyncResult ar)
{
  if ( null != _clientSocket )
  { 
     try
      {
        TransferStateObject state = null;
        lock(_syncRoot)
        {
          string message;
          state = (TransferStateObject)ar.AsyncState;
          int bytesRead = _clientSocket.EndReceive(ar);
          //bla bla bla
        }
      }
   }
  else
  {
    //socket has been closed/ is closing
   }
}

马里奥

【讨论】:

  • 我更新了问题。锁定在我放置的代码中以防止此时断开连接,然后套接字接收并计算一些信息
  • 重组没有帮助(现在在 EndReceive 方法出现空引用异常
  • 这个问题是仅在您完成连接/关闭应用程序时出现,还是在您接收数据时出现?
  • 只有当我完成连接时'socket.ShutDown();socket.Disconnect()' 也不起作用..尽管在客户端 socket.Connected = false 因此连接关闭.. 关闭服务器后抛出“连接中断”异常。
  • 您是否尝试在 OnBeginRead 中添加检查?我将其添加到我的帖子中!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-28
  • 2011-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多