首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用SocketAsyncEventArgs检测套接字关闭?

如何使用SocketAsyncEventArgs检测套接字关闭?
EN

Stack Overflow用户
提问于 2018-05-09 04:16:32
回答 1查看 313关注 0票数 0

当我尝试使用.Net的SocketAsyncEventArgs时,我遇到了一个有趣的场景。也就是说,它们似乎无法检测到何时发生了正常的远程套接字关闭。

背景知识:我正在将一个遗留应用程序从MFC更新到一个.NET项目,并且我的代码需要与所有其他遗留MFC代码进行交互。在传统的MFC代码中,当使用FIN或RST信号正常关闭远程连接时,MFC后端会自动注册。我在实践中观察到了这种行为,所有用户能够或需要与之交互的就是重载MFC提供的OnClose方法。

目前我不能用C#或C++/CLI复制它。我用来处理所有接收操作的SocketAsyncEventArgs如下所示:

代码语言:javascript
复制
static void AcceptHandler(System::IAsyncResult^ ar)
{
    ServerSocket ^server = (ServerSocket ^)ar->AsyncState;
    try
    {
       server->Socket = gcnew SocketMgr(server->listener->EndAcceptSocket(ar));
       //pConnectionCb a function variable I use for updating the GUI when
       //connection status changes. ReceiveDataHandler is another function
       //variable for logging purposes.
       if (server->pConnectionChangedCb)
       {
          server->pConnectionChangedCb(server->nID);
       }

       if (server->receiveDataHandler)
       {
          System::Net::Sockets::SocketAsyncEventArgs ^receiveArgs = gcnew System::Net::Sockets::SocketAsyncEventArgs();
          receiveArgs->SetBuffer(server->readbuffer, server->nOffset, server->nBytesToGet - server->nOffset);
          receiveArgs->Completed +=
              gcnew System::EventHandler<System::Net::Sockets::SocketAsyncEventArgs ^>(server, &ServerSocket::IO_Completed);
          server->Socket->ReceiveAsync(receiveArgs);
      }
   }
   catch (System::Net::Sockets::SocketException ^e)
   {
      System::Windows::Forms::MessageBox::Show("OnAccept: Could not Accept, exception" + e->ErrorCode);
      server->listener->EndAcceptSocket(ar);
   }
}
void IO_Completed(System::Object ^sender, System::Net::Sockets::SocketAsyncEventArgs ^e)
{
   if (!(e->SocketError == System::Net::Sockets::SocketError::Success))
   {
      kPrintf("Error.");
   }
   // determine which type of operation just completed and call the associated handler
   switch (e->LastOperation)
   {
   case System::Net::Sockets::SocketAsyncOperation::Receive:
      ProcessReceive(e);
      break;
   case System::Net::Sockets::SocketAsyncOperation::Send:
      ProcessSend(e);
      break;
   default:
      throw gcnew System::ArgumentException("The last operation completed on the socket was not a receive or send");
   }
};

根据我的观察,当远程套接字不复存在时,位于读取中间的SocketAsyncEventArgs对象将以一种尚未完成且永远不会完成的状态存在。当它无法完成时,IO_Completed将永远不会被调用,并且我将无法使用它来检测套接字何时发送正常断开连接。所以它不能被使用。

当然,...The唯一的问题是,在Socket.Net.Sockets.Socket或SocketAsyncEventArgs中没有OnRemoteClose (或等效的)事件可供我编写脚本,使我无法检测到套接字FIN或RST信号,并且使套接字保持打开的时间比预期的要长。C#可能有办法解决这个问题,但我无论如何也找不到它。以前还有没有人和这个搏斗过?

EN

回答 1

Stack Overflow用户

发布于 2018-05-09 07:52:43

事实证明,SocketAsyncEventArgs确实记录了任何远程套接字的正常终止,而与客户端语言无关。它不公开底层的TCP/IP事件或任何类似事件,而只是将套接字闭包演示为发送的空消息。

由于PEBKAC错误,我的代码没有接收到空的0字节消息,因此我永远不能“看到”正常的关机。

(如果将来有人遇到这个问题,问题是ProcessReceive方法应该在收到第一个信号后调用ReceiveAsync来继续循环,并且它...不是,因为与代码无关的原因。)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50241642

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档