TCP SOCKET 句柄可以继承吗?

2024-03-27

在 Windows 上,大多数类型的句柄都可以由子进程继承。期望 TCP 套接字也可以被继承。但是,当安装某些分层服务提供商时,这不会按预期工作(赛门铁克的 PCTools 等 A/V 产品曾经导致我们的客户应用程序出现问题)。

按照微软构建WinSock的方式,我们是否应该期望能够正确继承SOCKET?


简短回答

不,SOCKET 不应标记为可继承。安装某些分层服务提供程序 (LSP) 后,继承的句柄根本无法在子级中使用。

作为额外的刺激,请参阅相关问题“TCP SOCKETS 可以标记为不可继承吗?” https://stackoverflow.com/questions/12058911。简而言之,您不能依赖能够继承套接字,但也不能阻止套接字被继承!

解释

遗憾的是,这违背了微软自己的一些示例和文档(例如KB150523 http://support.microsoft.com/kb/150523)。简而言之,分层服务提供程序是 Microsoft 为第三方软件提供的一种将其自身插入到您的应用程序和 WinSock DLL 中的 Microsoft TCP/UDP 堆栈之间的方式。由于某些 LSP 的工作方式,它们使得在进程之间传输套接字变得困难,因为 LSP 将一些本地信息与其需要存在的每个套接字相关联。

LSP 只能挂接到 WinSock 函数;例如,调用DuplicateHandle当安装某些 LSP 时,SOCKET 上的功能将不起作用,因为它是句柄级函数,并且 LSP 永远没有机会复制其所需的信息。 (这在DuplicateHandle 文档 http://msdn.microsoft.com/en-us/library/windows/desktop/ms724251(v=vs.85).aspx).

类似地,尝试将 SOCKET 句柄设置为可继承将在不通知 LSP 的情况下复制该句柄,从而产生相同的结果:子进程中的 Winsock 可能无法识别重复的句柄。典型的错误是WSAENOTSOCK(10038,“非套接字上的套接字操作”),甚至ERROR_INVALID_HANDLE(6,“句柄无效”)。

Example

假设您要编写一个 Windows 程序,该程序使用重定向的 stdin 和 stdout 启动一个子进程,向其发送一些数据,在子进程的 stdin 上发出 EOF 信号,以便它知道要处理数据,然后等待子进程返回。

让我们进一步假设执行某种富有想象力的启动形式,这意味着您的孩子可能根本不是孩子(例如, gksu/runas 启动必须立即退出的包装器,只留下与客户端)。因此,您无需等待子进程的 PID。

该行为将与此类似:

int main(int argc, char* argv[]) {
  int handles[2];
  socketpair(AF_UNIX, SOCK_STREAM, 0, handles);
  if (fork()) {
    // child
    close(handles[0]);
    dup2(handles[1], 0);
    dup2(handles[1], 1);
    execl("clever-app", "clever-app", (char*)0);
  }

  // parent
  close(handles[1]);
  char* data[100];
  write(handles[0], data, sizeof(data)); // should at least check for EINTR...

  // tell the app we called there's nothing more to read from stdin: 
  shutdown(handles[0], SHUT_WR);

  // wait until child has exited (discarding all output)
  while (read(handles[0], data, sizeof(data)) >= 0) ;

  // now continue with the rest of the program...
}

解决方法

在没有分层服务提供程序的计算机上,创建一对连接的 TCP 套接字并在子级中继承一个套接字作为 stdin/stdout,确实会正常运行。使用它作为解决方法很诱人socketpairWindows 上的行为(记住发送随机数!)。

遗憾的是,SOCKET 根本无法可靠地继承。要在 Windows 上编写具有几乎相同功能的东西,您需要使用命名管道。致电之前CreateProcess,创建一对连接的 HANDLES,而不是使用CreateNamedPipe/ConnectNamedPipe和朋友 (GetOverlappedResult对于重叠的父句柄)。 (子进程的句柄要用作标准输入,不能重叠!)子进程的句柄可以设置为可继承,子进程将通过它正常通信。

当您完成向客户端传输数据后,调用FlushFileBuffers and CloseHandle在父句柄上。

进一步的问题

  1. 只使用句柄等待孩子退出后再继续怎么样?没有办法直接通过管道来做到这一点;窗户管道不能半封闭。执行此操作的方法:

    1. (Unix方式,扭曲以适应Windows)制作另一对虚拟的连接句柄,并在子进程中继承其中一个,但不要告诉子进程(不要将其附加为标准句柄)。然后,您可以等待父级中的第二个句柄来检测子级何时退出。
    2. (Windows 方式)确实很痛苦,但相当强大:使用命名管道获取父级中子级的实际进程句柄。这是 Windows 上等待子进程退出的“正确”方法。 (这实际上在Unix上是做不到的;只有进程的父进程才能直接等待进程退出;OpenProcess将 pid 转换为句柄,因此如果您在OpenProcess调用,你可以摆脱在 Unix 上不可能实现这一点的竞争条件。)使用这样的进程句柄仍然是一个痛苦的事情,因为你可能会发现你需要第二个命名管道连接来发送它,具体取决于关于如何编写 runas 包装器。
  2. 问题:子级如何接收父级已完成对其标准输入的写入的通知?如果家长尝试打电话DisconnectClient,孩子没有得到正常的 EOF。根据您尝试执行的内容,这可能是一个问题。当父母关闭一个 SOCKET 时,你会得到feof,但是如果句柄连接到子进程的 stdin,则子进程将收到读取错误,而不会收到 EOF 信号。这可能会导致子进程的工作方式与正常连接到 stdin 时的工作方式不同。相反,在父级中调用 CloseHandle 会在子级中提供正确的行为。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TCP SOCKET 句柄可以继承吗? 的相关文章

  • 在 Windows 任务栏中对单独的进程进行分组

    我有许多逻辑上相关的独立进程 但所有进程都是单独启动的 没有共同的 父 进程 是否可以使它们在 Windows 任务栏中显示为一组 工作样本 这是一些受雷米答案启发的工作代码 using System using System Runtim
  • 确定用winsock(FIONWRITE)可以发送多少字节?

    通过 select 我可以确定是否可以在不阻塞的情况下接收或发送任何字节 通过这个函数 我可以确定可以接收多少字节 function BytesAvailable S TSocket Integer begin if ioctlsocket
  • Windows EventLog:它的操作速度有多快?

    我有一个服务应用程序 它通过 TCP 处理客户端请求并将任何事件写入 Windows EventLog 由于该应用程序预计会在短时间内为许多客户端和每个客户端的大量请求提供服务 假设每秒 1 到 50 个请求 因此我很想知道密集程度 CPU
  • 获取正在运行的程序的属性

    我想开发一个程序 其 ID 是一张牌 因为它在另一个正在运行的程序 例如扑克或红心游戏或其他程序 中播放 我首先尝试获取有关已运行的游戏程序的所需信息 但我从一开始就遇到了问题 我正在运行 MSVC 2013 并开发 MFC 应用程序 现在
  • 如何在win32上安装OpenCV 2.0

    我需要在 Win32 上安装 OpenCV 我目前没有安装它 我下载了 OpenCV 2 0 0a win32 exe 并运行它 我现在到底该怎么办 没有 lib之类的东西 我找到了一些使用 cmake 构建版本的说明 http openc
  • 如何以编程方式重新启动 Windows 资源管理器进程

    我正在开发 Windows shell 扩展 不幸的是 在更改 DLL 时 我必须重新启动 Windows 资源管理器 因为它将 DLL 保留在内存中 我从 Dino Esposito 找到了这个程序 但它对我不起作用 void SHShe
  • Windows XP 风格:为什么我们在静态文本小部件上得到深灰色背景?

    我们正在使用 C 和 Win32 编写 Windows 桌面应用程序 我们的对话框具有 Windows XP 风格 的丑陋外观 静态文本的背景是灰色的 如果对话框背景也是灰色 这不是问题 但在背景为白色的选项卡控件内 文本的灰色背景非常明显
  • C++ win32设置光标位置

    我知道要使用哪个功能 但我无法让它正常工作 我用了SetCursorPos 唯一的问题是它将光标设置为屏幕坐标而不是窗口坐标 我也尝试过ScreenToClient 但它并没有起作用 这是我的代码 pt x 113 pt y 280 Scr
  • Windows下如何分配非分页内存

    当我使用 cudaHostAlloc 时 它将分配非分页 固定 页面锁定 内存 我想知道如何在没有 cuda 的情况下仅使用 Windows SDK 来做到这一点 None
  • HWND 创建时间

    我是这个社区的新手 在使用我的自动化脚本 1 时遇到一个问题 我想获取 HWND 的创建时间 我在从 FindWindowEx 检索到的数组中有一组 HWND 我想在数组中找到最后根据系统时间创建的 HWND 我对窗口钩子没有足够的了解 但
  • 在 C# 中打开的资源管理器窗口中获取文件/目录列表

    我试图拉出打开的资源管理器窗口中列出的文件和目录列表 与显示的顺序相同 以便我可以查看它 然后将焦点设置到特定项目 我找到了这段代码here https stackoverflow com questions 14193388 how to
  • winapi 函数的函数指针 (stdcall/cdecl)

    请有人给我一些为 MS winapi 函数创建函数指针的提示吗 我试图为 DefWindowProc DefWindowProcA DefWindowProcW 创建一个指针 但出现此错误 LRESULT dwp HWND UINT WPA
  • 检测 Windows 重新启动是否是由于 Windows 更新造成的

    我的电脑上的一些应用程序一直在检测 Windows 更新是否重新启动 这是可以观察到的 因为它们会在 Windows 更新自动重启后重新启动 这非常有帮助 因为这些应用程序会重新加载更改 甚至unsaved更改或恢复选项卡 如果是浏览器 执
  • 链接到大地址感知 DLL

    假设我有一个使用 LARGEADDRESSAWARE 链接器标志集构建的 DLL 现在我有一个动态链接到该 DLL 的应用程序 这是否会使我的应用程序具有大型地址意识 如果不是 那么为任何 DLL 设置此标志是否有意义 讨论here htt
  • 使用API​​隐藏程序标题栏

    它可以使用 c 和 windows api 删除窗口控制台标题栏 如果是的话如何 请 这个简单的应用程序隐藏并显示其所在控制台的标题栏 它会立即将控制台标题更改为 guid 以查找窗口句柄 然后 它使用 ToggleTitleBar 使用找
  • 如何通过API退出Win32应用程序?

    我有一个使用 Win32 API 编写的 C Win32 应用程序 我希望强制它在其中一个函数中退出 有没有类似的东西Exit or Destroy or Abort 类似的东西会终止它吗 哎呀呀呀呀呀呀 不要做任何这些事情 exit 和
  • win32 API 和 .NET 框架之间的选择

    我必须开发一个适用于 Windows 的应用程序 该应用程序将能够通过网络摄像头识别手势来控制鼠标 我将使用 vc 2008 进行开发 但我很困惑是使用 NET 框架还是核心 win32 API 性能对于我的应用程序非常重要 根据 Ivor
  • 监控进程的网络使用情况?

    C 或 C C Win32 中有没有一种方法可以监视某个进程的网络使用情况 显然没有您构建的应用程序 我想只监视 1 个进程大约一个小时左右 然后返回仅该进程 例如 Limewire 使用的字节 是否可以 我知道 Windows 上的 ne
  • C# - 如何将 IntPtr 缓冲区数据保存到文件(最快的方法)?

    我使用此代码将非托管代码中的 IntPtr 缓冲区中的字节保存到文件中 这是一个简单的回调函数 private void callback IntPtr buffer int length byte bytes new byte lengt
  • 检查Windows电源管理是否关闭了显示器

    如何在 Windows 7 和 XP 中以编程方式检查 Windows 电源管理 是否已关闭显示屏 如果能收到一个活动就更好了 我不认为 XP 可以做到这一点 Windows 7 中有各种与电源管理相关的好东西 这Windows API 代

随机推荐

  • 构建哈希表/哈希函数

    我想构建一个哈希表 用于查找 1 到 15 个字节的字节序列 字符串 中的键 我想存储一个整数值 所以我想一个用于散列的数组就足够了 我很难概念化如何构造一个哈希函数 以便给定的键将给出数组的索引 任何帮助将不胜感激 哈希中的最大条目数为
  • 在基类中实现 Swift 协议方法

    我有一个 Swift 协议 它定义了如下方法 protocol MyProtocol class func retrieve id String gt Self 我有几个符合此协议的不同类 class MyClass1 MyProtocol
  • 如何使用 AS3 单击 Flash 中的显示对象?

    我正在创建一个照片编辑器应用程序 在某些时候 您编辑的照片应该放置在两层 DisplayObjects 背景图像和图像蒙版 之间 但有一个问题 当您正在编辑的图像被放置在背景层和图像遮罩层之间时 它变得不可点击 因此卡在那里 没有机会再次拖
  • Boto:从配置中动态获取Python代码中的aws_access_key_id和aws_secret_access_key?

    我有我的aws access key id and aws secret access key存储在 boto我想知道是否有办法使用 Boto 在我的 python 代码中检索这些值 因为我需要将它们插入到我的 SQL 语句中以从 S3 复
  • Azure:从应用服务访问 Key Vault 时如何修复“策略要求调用者‘...’使用代表 (OBO) 流”?

    我有一个在 Azure 应用服务中运行的 ASP net Core 3 1 应用程序 开始使用 Azure Key Vault 存储应用程序的连接字符串和其他机密后 该应用程序现在崩溃并显示以下错误 HTTP 错误 500 30 ANCM
  • 从 serverless.yml 中引用函数

    我有几个正在运行的 AWS lambda 由无服务器框架 我需要一个 lambda 称为lambdaOne 这将调用第二个 lambda 称为lambdaTwo 使用 AWS 的 javascript sdk 问题是我得到了AccessDe
  • RDF和OWL工作流程问题

    我一直在通过 Protege 查看和使用 OWL 我想知道我是否正确理解 工作流程 和它的想法 从头开始构建数据库 使用 Protege 或等效工具为您的数据生成 OWL 本体 将此模式导出为 RDF 使用定义为三元组中的某些元素的类以及目
  • .NET 在为 WCF 服务生成类型时加载并寻找另一个版本的程序集

    我在 Visual Studio 2013 中尝试向 ASP NET Web 应用程序添加服务引用时遇到此错误 我在项目中引用了 Microsoft Owin Security 版本 2 1 0 0 但我很沮丧为什么他要寻找2 0 1 0版
  • 使用数据库优先方法为 Entity Framework 5 中的所有实体创建基类

    我在每个表上都有一些属性 例如 CreatedDate ModifiedDate VersionNo 每次修改实体时 我都需要更改 添加这些属性的值 我认为我可以使用这些属性创建一个基类 并让实体从该基类派生 并且在基于 ObjectSta
  • 每个数据库名称 Ansible 运行一次任务

    我正在使用 ansible 将多个站点部署到同一服务器 每个站点都是 ansible 中的一个单独的 主机 hosts库存 效果非常好 但是 只有两个数据库 生产数据库和测试数据库 如何确保每个数据库只运行一次数据库迁移任务 我读过grou
  • 可以弹簧@Autowired Map吗?

    这是地图 Autowired private Map
  • Google appengine blobstore 上传处理程序处理额外的表单发布参数

    我希望有一个文件上传表单 除了文件选择输入之外 还具有其他输入字段 如文本区域 下拉列表等 问题是我无法访问除 blobstore 上传处理程序中的文件之外的任何发布参数 我使用以下函数调用来获取参数名称 但它始终返回空屏幕 par sel
  • PHP 中的 HTTP_HOST 和 SERVER_NAME 有什么区别?

    有什么区别 SERVER HTTP HOST and SERVER SERVER NAME in PHP 您什么时候会考虑使用其中一种而不是另一种 为什么 The HTTP HOST是从获得HTTP 请求头 http www w3 org
  • popToRootViewControllerAnimated 并释放所有视图

    我有一个 UINavigationController 它要求提供一些信息 用户导航直到最后 一旦到达那里 他们就可以接受或取消所有已输入的数据 他们选择哪个选项并不重要 因为他们总是会使用 UINavigationController p
  • 统一更新:使用本地文件的更新更新私有存储库(重构、重命名、更新)并从原始存储库获取定期更新

    我刚刚开始学习 Windows 上的 GitHub CLI 工具 认为我是新手 我有一个如下所示的用例 在深入探讨之前 让我先总结一下 我的用例是 克隆一个开源项目 它更新 定期 即创建它的本地副本并进行修改 包括 重命名文件和文件夹 将更
  • 准备重用

    有人可以告诉我如何使用prepareForReuse吗 我已经搜索了几个小时并阅读了开发文档 在扩展 UITableViewCell 的自定义单元中 我有prepareForReuse 方法及其被调用 但我该如何处理它 存在渲染问题 我这样
  • 有没有办法让无线电组水平布局?

    我在单选按钮组内有 2 个单选按钮 现在它们垂直排列 我尝试将它们放入水平容器中 但没有用 有没有办法让一组单选按钮水平排列
  • 在当前位置插入文本 TINYMCE IE9

    如何将文本插入到tinyMce编辑器的当前位置 它在 Chrome FF Safari 中完美运行 但在 IE 中它始终从文本区域的顶部开始 我目前执行以下操作 tinyMCE execCommand mceInsertContent fa
  • 如何在c中创建一个n维数组

    我正在考虑编写一个函数 它接受 n 个参数并使用这些参数作为维度返回一个 n 维数组 现在我意识到一维和二维数组很容易用指针实现 对于二维数组 片段将类似于 标准方式 int x int temp x int malloc m sizeof
  • TCP SOCKET 句柄可以继承吗?

    在 Windows 上 大多数类型的句柄都可以由子进程继承 期望 TCP 套接字也可以被继承 但是 当安装某些分层服务提供商时 这不会按预期工作 赛门铁克的 PCTools 等 A V 产品曾经导致我们的客户应用程序出现问题 按照微软构建W