命名管道服务器,如何中断或超时等待客户端连接和传入数据

2024-01-10

我正在为 Windows 编写一个简单的命名管道服务器,调用 Windows API(在 Java 中使用 JNA,但这不相关)。

我试图找出如何避免服务器永远卡住等待客户端连接或来自客户端的数据。

服务器代码执行以下操作:

1)它通过调用创建管道CreateNamedPipe https://msdn.microsoft.com/en-us/library/windows/desktop/aa365150%28v=vs.85%29.aspx, with PIPE_WAIT in the dwPipeMode争论。

2)它调用ConnectNamedPipe https://msdn.microsoft.com/en-us/library/windows/desktop/aa365146%28v=vs.85%29.aspx在客户端连接之前不会返回。

3) 它进入一个循环,通过调用重复从客户端读取消息ReadFile https://msdn.microsoft.com/en-us/library/windows/desktop/aa365467%28v=vs.85%29.aspx在读取数据之前不会返回,并且对于每条收到的消息,它都会通过调用将消息发送回客户端作为响应WriteFile.

4) 经过多次这样的对话,客户端和服务器将断开与管道的连接。

我只是希望能够在等待中设置超时ConnectNamedPipe在步骤 2 和ReadFile在第 3 步,我看不到在哪里设置超时。有的是nDefaultTimeOut论证中CreateNamedPipe功能,但听起来并不是真正的目的; API 文档说:

默认超时值,以毫秒为单位,如果WaitNamedPipe函数指定NMPWAIT_USE_DEFAULT_WAIT.

So the nDefaultTimeOut arg in CreateNamedPipe听起来像默认超时客户它将连接到管道将用于他们的操作,并且只有当他们调用WaitNamedPipe功能。事实上,在我的测试中,0 或 1000 的值没有什么区别,调用ConnectNamedPipe永远不会返回(除非客户端连接)。我正在寻找的是服务器中的超时,而不是调用ConnectNamedPipe and ReadFile.

作为文档CreateNamedPipe https://msdn.microsoft.com/en-us/library/windows/desktop/aa365150%28v=vs.85%29.aspx, 为了dwPipeMode与争论PIPE_WAIT says, Blocking mode is enabled. When the pipe handle is specified in the ReadFile, WriteFile, or ConnectNamedPipe function, the operations are not completed until there is data to read, all data is written, or a client is connected. Use of this mode can mean waiting indefinitely in some situations for a client process to perform an action.

因此,也许实现此类超时的方法是以非阻塞模式创建管道(使用PIPE_NOWAIT代替PIPE_WAIT)这样就可以调用ReadFile, WriteFile and ConnectNamedPipe立即返回,然后以某种方式监视自己循环中的事件(客户端连接或接收数据),并在循环中检查自己是否超时或发生另一个中断事件(例如用户单击“取消”按钮)?

ADDED: 看起来像ReadFile打电话我也许可以使用PeekNamedPipe它立即返回,检查是否有数据要读取,然后调用ReadFile。我会尝试一下。但我仍然遇到同样的问题ConnectNamedPipe.

ADDED:正如我怀疑的那样,答案也证实了这一点,作为管道的新手,我从某种倾斜的角度看待它们,从这个角度来看,对超时的需求似乎比实际情况更大。

F. 前。想要超时调用背后的原因ReadFile是,如果我(服务器)在其中从客户端读取数据并且客户端突然关闭,有时我可能最终会陷入困境ReadFile。但现在我知道如果ReadFile正在从管道读取并且客户端关闭,ReadFile will always错误输出,因此执行不会卡在其中。


一些实际代码演示了 GUI 应用程序中管道服务器端的异步使用:

void wait_for_object(HANDLE object)
{
  DWORD dw;
  MSG msg;

  for (;;) 
  {
    dw = MsgWaitForMultipleObjectsEx(1, &object, INFINITE, QS_ALLINPUT, 0);

    if (dw == WAIT_OBJECT_0) break;
    if (dw == WAIT_OBJECT_0 + 1) 
    {
      while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
      continue;
    }
    srvfail(L"sleep() messageloop", GetLastError());
  }
}

HANDLE server_pipe;
HANDLE io_event;

void pipe_connection(void)
{
    OVERLAPPED overlapped;
    DWORD dw, err;

    SecureZeroMemory(&overlapped, sizeof(overlapped));
    overlapped.hEvent = io_event;

    if (!ReadFile(server_pipe, input_buffer, sizeof(input_buffer) - 1, NULL, &overlapped))
    {
        err = GetLastError();
        if (err == ERROR_IO_PENDING)
        {
            wait_for_object(io_event);
            if (!GetOverlappedResult(server_pipe, &overlapped, &dw, FALSE)) 
            {
                srvfail(L"Read from pipe failed asynchronously.", GetLastError());
            }
        }
        else
        {
            srvfail(L"Read from pipe failed synchronously.", GetLastError());
        }
    }
    else
    {
        if (!GetOverlappedResult(server_pipe, &overlapped, &dw, FALSE)) 
        {
            srvfail(L"GetOverlappedResult failed reading from pipe.", GetLastError());
        }
    }

    input_buffer[dw] = '\0';

    process_command();

    if (!WriteFile(server_pipe, &output_struct, 
        ((char *)&output_struct.output_string - (char *)&output_struct) + output_struct.string_length, 
        NULL, &overlapped))
    {
        err = GetLastError();
        if (err == ERROR_IO_PENDING)
        {
            wait_for_object(io_event);
            if (!GetOverlappedResult(server_pipe, &overlapped, &dw, FALSE)) 
            {
                srvfail(L"Write to pipe failed asynchronously.", GetLastError());
            }
        }
        else
        {
            srvfail(L"Write to pipe failed synchronously.", GetLastError());
        }
    }
    else
    {
        if (!GetOverlappedResult(server_pipe, &overlapped, &dw, FALSE)) 
        {
            srvfail(L"GetOverlappedResult failed writing to pipe.", GetLastError());
        }
    }

    if (!FlushFileBuffers(server_pipe)) srvfail(L"FlushFileBuffers failed.", GetLastError());
    if (!DisconnectNamedPipe(server_pipe)) srvfail(L"DisconnectNamedPipe failed.", GetLastError());
}

void server(void)
{
    OVERLAPPED overlapped;
    DWORD err, dw; 

    // Create the named pipe

    server_pipe = CreateNamedPipe(pipe_name, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, buffer_size, buffer_size, 0, NULL);
    if (server_pipe == INVALID_HANDLE_VALUE) srvfail(L"CreateNamedPipe failed.", GetLastError());

    // Wait for connections

    io_event = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (io_event == NULL) srvfail(L"CreateEvent(io_event) failed.", GetLastError());

    for (;;)
    {
        SecureZeroMemory(&overlapped, sizeof(overlapped));
        overlapped.hEvent = io_event;

        if (!ConnectNamedPipe(server_pipe, &overlapped))
        {
            err = GetLastError();
            if (err == ERROR_PIPE_CONNECTED)
            {
                pipe_connection();
            }
            else if (err == ERROR_IO_PENDING)
            {
                wait_for_object(io_event);
                if (!GetOverlappedResult(server_pipe, &overlapped, &dw, FALSE)) 
                {
                    srvfail(L"Pipe connection failed asynchronously.", GetLastError());
                }
                pipe_connection();
            }
            else
            {
                srvfail(L"Pipe connection failed synchronously.", GetLastError());
            }
        }
        else
        {
            if (!GetOverlappedResult(server_pipe, &overlapped, &dw, FALSE)) 
            {
                srvfail(L"GetOverlappedResult failed connecting pipe.", GetLastError());
            }
            pipe_connection();
        }
    }
}

(此代码已从原始代码中进行了编辑,以删除无关的逻辑。我还没有尝试编译编辑后的版本,因此可能存在一些小问题。另请注意全局变量的使用,这在我的情况下是可以的,因为应用程序很小,但是应该usually应避免。)

使用 MsgWaitForMultipleObjectsEx() 允许在等待 I/O 完成时处理窗口消息。如果您还在等待其他事情发生,则可以向其传递一个句柄数组,而不仅仅是一个句柄 - 例如,如果您想监视子进程并在其退出时执行某些操作,则可以传递一个包含以下内容的数组:两个都io_event和进程句柄。如果你只是had要定期执行其他工作,您可以设置等待超时,或使用窗口计时器。

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

命名管道服务器,如何中断或超时等待客户端连接和传入数据 的相关文章

  • 如何在 bash 中结合超时和 eval 命令

    为了执行存储在变量中的命令eval使用命令 gt a echo e a nb wc l gt eval a 2 但如何才能与它结合起来呢 timeout命令 我尝试过以下操作 这给了我错误的输出 gt timeout 10 a a b wc
  • win32 API 和 .NET 框架之间的选择

    我必须开发一个适用于 Windows 的应用程序 该应用程序将能够通过网络摄像头识别手势来控制鼠标 我将使用 vc 2008 进行开发 但我很困惑是使用 NET 框架还是核心 win32 API 性能对于我的应用程序非常重要 根据 Ivor
  • 使用 Git 的 Spring Cloud 配置服务器 - 无法克隆或签出存储库连接超时

    我正在使用 GIT 在 Spring Cloud Config Server 上进行 POC Spring Boot 1 5 3 RELEASE 爪哇1 8 弹簧工具套件https github com kishornpatil https
  • 如何取消同步 WinHttp 请求?

    我的服务有一个线程可能正在执行WinHttpSendRequest当有人试图停止我的服务时 The WinHttpCloseHandle 文档 http msdn microsoft com en us library windows de
  • 怎样才能使 Windows 成为一个开箱即用的 POSIX 兼容操作系统?

    这个问题的动机是我的一个牵强的梦想 即 nix 平台上可用的许多优秀软件可以轻松移植到 Windows 微软最近对开源和开放性采取了不同的方法 所以我真的很想知道如果微软有这样的倾向 这样的事情会有多可行 我很好奇的一些更具体的事情是 是否
  • Git 子模块:[电子邮件受保护]:权限被拒绝(公钥)。致命:无法从远程存储库读取

    我有一个问题git submodule update init remote 我收到错误 权限被拒绝和克隆失败 但我将 SSH 密钥添加到了我的 github 存储库中 我可以拉 推 git 克隆 我拥有所有需要的访问权限 我使用操作系统
  • 监控进程的网络使用情况?

    C 或 C C Win32 中有没有一种方法可以监视某个进程的网络使用情况 显然没有您构建的应用程序 我想只监视 1 个进程大约一个小时左右 然后返回仅该进程 例如 Limewire 使用的字节 是否可以 我知道 Windows 上的 ne
  • 如何通过批处理文件检查服务是否正在运行并启动它,如果它没有运行?

    我想编写一个执行以下操作的批处理文件 Check if a service is running 如果正在运行 请退出批处理 如果没有运行 启动该服务 到目前为止 我在谷歌上搜索的代码示例被证明不起作用 所以我决定不发布它们 启动服务是通过
  • 什么是特权指令?

    我添加了一些可以干净编译的代码 并且刚刚收到此 Windows 错误 MonTel Administrator 2 12 7 MtAdmin exe Application Error The exception Privileged in
  • 通过注册表将上下文菜单项添加到特定扩展

    首先我们要说的是 我使用的是 Windows 10 并且我看过很多有关此主题的帖子 但似乎没有一个适合我 查看这篇文章已经解决了一些问题 但我仍然需要一些帮助 仅针对特定文件类型将菜单项添加到 Windows 上下文菜单 https sta
  • 在 powershell 脚本中以不同用户身份本地运行代码块

    这是非常简单的事情 但我就是无法让任何东西发挥作用 我想在特定用户下的 powershell 脚本中运行块代码 关键字是locally我正在使用 powershell 2 0 Invoke Command 似乎需要远程主机 我运行以下命令
  • 如何检测Windows版本是否合法? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我对获取版本信息不感兴趣 我想做的就是确保我的应用程序只能在合法版本的 Windows 上运行 而不是在盗版版本上运行 Windows 使
  • 在 C# 中使用反射列出枚举中的值

    我正在尝试使用反射来列出一个 Visual Studio 解决方案内的各个项目中的一些类的公共成员和方法 我尝试访问的所有类都是 C 的 并且它们都是从 C 类访问的 我用来进行这些调用的代码如下 public void PopulateE
  • Windows平台下C语言控制串口DTR和RTS引脚

    如何在windows平台上控制串口的DTR和RTS引脚 我希望通过升高或降低电压来对其进行位敲击或操作 您需要使用EscapeComm 函数 https learn microsoft com en us windows desktop a
  • 在 wampserver 2.2 上安装 php_imagick.dll PHP 扩展

    我使用的是 32 位操作系统的 Windows 7 我安装了 ImageMagick 6 8 7 Q16Link https www imagemagick org script download php windows我能够从命令行 转换
  • RestSharp RestClient的默认超时值是多少?

    任何人都知道默认超时值休息锐利 https github com restsharp 休息客户端 RestSharp 在底层使用 HttpWebRequest 它有一个默认超时 https msdn microsoft com en us
  • windows关闭tomcat后保持端口锁定

    我遇到了一个问题 该问题发生在不同站点的 3 台不同服务器上 问题是 当我关闭 Windows 服务器上的 Tomcat 7 和 8 5 版本 服务并尝试重新启动该服务后 该服务将无法启动 因为 tomcat 认为端口仍在使用中 以下是错误
  • 没有端点在 net.pipe://localhost/ 上监听

    我有两个 WCF 服务托管在 Windows Server 2003 计算机上的单个 Windows 服务中 如果 Windows 服务需要访问任一 WCF 服务 例如发生定时事件时 它将使用公开的五个命名管道端点之一 不同的服务协定 该服
  • 如何保证对象只有一个线程

    我有以下代码 class Service public void start creates thread which creates window and goes to message loop void stop sends WM C
  • 使用taskkill停止Windows服务

    我需要帮助来使用 C 终止 Windows 服务 现在要终止该服务 请使用以下选项 从命令 sc queryex ServiceName 发现后PID服务的 taskkill pid 1234 exemple f 为了便于阅读 但如果您明白

随机推荐

  • 如何让 Gradle 在 Java 测试之前编译 Groovy 测试

    Gradle 的 Groovy 插件声称它 supports joint compilation which allows to freely mix and match Groovy and Java code with dependen
  • 如何使用 java 将逗号 (,) 替换为点 (.)

    我有一个String str 12 12我想用 点 替换 逗号 以进行十进制数计算 目前我正在尝试这个 if str indexOf 1 str replaceAll 请帮忙 您的问题不在于匹配 替换 而是 String 是不可变的 您需要
  • 类型化的函数数组

    我正在努力弄清楚是否可以在 TypeScript 中声明静态类型的函数数组 例如 我可以这样做 foo data string gt void function data 但是 如果我希望 foo 成为一个接受字符串且不返回任何内容的函数数
  • D3 V4 中地图中的圆圈显示的位置不正确

    我正在使用教程来学习如何在 D3 v3 中生成地图 但我正在使用 D3 v4 我只是想让一些圆圈出现在地图上 见下文 该代码有效 只是圆圈位于内华达州上空并且应该位于湾区 我想这是地图投影和投影坐标之间的不匹配 我不确定地图所在的投影 但我
  • dplyr 用于行分位数

    我有一个 df 层 每个层都有 1000 个来自该层估计值的后验分布的样本 mydf lt as data frame lapply seq 1 1000 rnorm n 100 colnames mydf lt paste s seq 1
  • 将其他编辑器与 TortoiseHg 一起使用

    我正在尝试使用 TortoiseHG 的其他编辑器 而不是 Windows 记事本 我已经尝试过这里提到的解决方案 Mercurial 和 Notepad 集成 https stackoverflow com questions 92078
  • 我可以改进这个 JQuery 图像替换代码吗?

    HTML 看起来有点像 dl dt img src Something 1 dt dd Something 1 Text dd dl 此 HTML 重复 1 次或多次 因此同一页面上可能有许多 HTML 实例 我用来扩展 dd 并替换图像的
  • REST、HTTP DELETE 和参数

    向 HTTP DELETE 请求提供参数是否存在非 RESTful 的情况 我的场景是 我正在建模 您确定要删除它吗 设想 在某些情况下 资源的状态表明请求的删除可能无效 您可能可以自己想象一些需要确认删除的场景 我们采用的解决方案是向删除
  • 盐是否需要随机才能保护密码哈希?

    我对安全性知之甚少 我需要找到基础知识的基本解释 并且正在尝试想出一种合理的方法来使用 Net 将用户密码存储在数据库中 这是我当前的解决方案 private static byte HashPassword string password
  • 从 .Net 打印服务器端(不带 WinForms)

    嘿 印刷迷需要一些指导来引导我朝着正确的方向发展 我正在为当地一家商店开发一个 epos 系统 稍后我们将把它与一个电子商务网站结合起来 epos 系统的前端将是 WinForms 因此我们可以轻松处理 USB 设备 并且我们将使用 Web
  • 如何将常规 numpy 数组转换为记录数组?

    我读了一系列数字 np array f read split dtype np float64 然后我使用以下方法将其转换为二维数组np reshape 之后如何转换arr到记录数组 我尝试过 类似 以下操作 filename unstru
  • 使用 bash 脚本在 EC2 实例上启动会话管理器后如何在 EC2 实例上运行命令?

    我正在编写 bash 脚本来使用会话管理器在 ec2 实例上安装缺少的补丁 我可以使用脚本启动会话 但我不确定如何使用脚本在其上运行命令 instanceid i 098xxxx echo instanceid echo instance
  • Snowflake 身份验证令牌已过期 (390114) - Snowflake-SQLAlchemy 是否有心跳代码?

    我开发了一个 Flask 应用程序 使用 SQLAlchemy 连接到 Snowflake DB 作为后端 如果网站闲置时间超过 4 小时 我会遇到 Snowflake 身份验证令牌过期问题 我在谷歌上查了一下并找到了答案 https gi
  • jQueryUI 手风琴 - 每页可以有多个吗?

    我对 jQuery 很陌生 但已经找到了手风琴小部件并让它在大部分情况下都可以工作 我的问题是 一页上是否可以有多个手风琴 我有几个列表需要在视觉上分开 并且每个列表都需要是自己独立的手风琴 到目前为止 这是我的代码
  • Typescript 中动态导入模块的类型/类是什么?

    我在打字稿中查找导入模块的类型时遇到问题 有人可以帮助我吗 为了澄清我的问题我有一个模块module ts export class RSL1 然后我将其加载到我的index ts with const script await impor
  • 单击锚点时如何设置/存储 cookie

    我正在尝试使用 Cookie 以便引用单击的锚标记应用默认样式或特定样式 即使浏览器关闭 重新打开也是如此 因此 如果用户单击第二个链接 关闭或刷新浏览器并重新打开 则样式应仍处于活动状态 如果这是第一次 则应应用默认样式 这有点超出了我的
  • 如何测试 Greasemonkey 脚本,尤其是在网页的本地副本上?

    我有自己的 javascript 需要用 Greasemonkey 进行测试 我以前从未与 Greasemonkey 合作过 我如何测试脚本 我没有在万维网上测试它 我已经保存了目标页面 Firefox gt 将页面另存为 gt 网页 完成
  • 如何将条件必需属性放入类属性中以与 WEB API 一起使用?

    我只想放条件必需属性这是与WEB API Example public sealed class EmployeeModel Required public int CategoryId get set public string Emai
  • 有没有一种简单的方法可以将此文本解析为地图

    我收到以下服务的响应 如何将其解析为Map 我首先想到在空白处分割 但它不起作用 因为该值可能包含空格 例如看看的价值SA键入以下响应 我想到的一种选择是在空白处分割provided前面的字符是双引号 但不知道如何为此编写正则表达式 TX
  • 命名管道服务器,如何中断或超时等待客户端连接和传入数据

    我正在为 Windows 编写一个简单的命名管道服务器 调用 Windows API 在 Java 中使用 JNA 但这不相关 我试图找出如何避免服务器永远卡住等待客户端连接或来自客户端的数据 服务器代码执行以下操作 1 它通过调用创建管道