You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

System.Net.Sockets.Socket.Disconnect底层逻辑与挂钩检测方案咨询

问题解答

System.Net.Sockets.Socket.Disconnect 底层调用逻辑

你之前挂钩的WinSock函数没有捕获到调用,核心原因是你伪造的Socket从未被标记为已连接状态,.NET Runtime的托管层校验会直接抛出你看到的SocketException,根本不会走到下层非托管WinSock接口调用的步骤。

正常情况下,Windows平台下面向连接的Socket(如TCP)执行Disconnect(Boolean reuseSocket)的完整流程为:

  • 第一步托管层校验Socket状态:通过调用WinSock的getpeername、或者读取SO_CONNECT_STATE套接字选项判断Socket是否处于已连接状态,如果未连接直接抛出异常,终止后续流程
  • 第二步如果校验通过,首先调用shutdown(SHUT_SEND)关闭Socket的发送通道
  • 第三步调用WSASendDisconnect发送断开连接通知,等待对端响应
  • 第四步如果reuseSocket参数为true,调用setsockopt设置SO_REUSEADDR选项
  • 第五步如果是同步Disconnect调用,会等待所有未完成的IO操作结束后返回

卡顿原因

你实现的recv钩子采用无限循环等待数据,C#程序触发Disconnect抛出异常后,异常处理逻辑会等待当前未完成的IO操作(也就是你阻塞的recv调用)结束,无限循环没有退出信号自然会导致程序卡顿。

解决方案&需要额外挂钩的函数

  • 首先新增挂钩getpeername和getsockopt:对你自己拦截伪造的Socket,在这两个函数的钩子里直接返回成功,伪造已连接的状态和假的对端地址,让Disconnect可以通过托管层校验,继续执行后续的WinSock调用
  • 已经挂钩的shutdown函数不需要修改逻辑,但是要补充:在shutdown的处理逻辑中添加对对应Socket的recv循环的终止信号,不用等到closesocket被调用才终止循环,Disconnect流程会优先调用shutdown,这一步就能结束阻塞的recv逻辑
  • 如果是.NET Core/.NET 5+的程序,还可以额外挂钩WSADisconnectEvent这个相对冷门的WinSock扩展函数,部分版本的.NET Runtime会调用这个函数处理断开逻辑

额外说明

如果不想修改状态伪造逻辑,也可以在你的recv循环里增加超时检测,或者定期检查当前Socket的状态标记,一旦发现上层程序已经触发了断开相关的操作就主动退出循环,避免永久阻塞。

内容的提问来源于stack exchange,提问作者user13095983

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.19 03:24:01