如何在 Windows 中随时(同时)发送数据?

Posted

技术标签:

【中文标题】如何在 Windows 中随时(同时)发送数据?【英文标题】:how to send data at any moment ( simultaneous ) in windows? 【发布时间】:2019-01-13 14:41:40 【问题描述】:

我想在windows OS下写一个namedpipe客户端,即使客户端正在接收数据,它也可以随时发送数据。MSDN的Example只表示接收后发送数据。而串行操作不是我想要的.因为我在客户端和服务器之间传输的数据不是很大,也就是说IO操作应该不是一个耗时的过程,所以我没有在客户端使用OVERLAP

我在客户端的 MSDN 示例中修改的代码如下: 主线程不断读取数据,子线程不断向服务器发送数据。但是,调试时读取数据时服务器阻塞了。

std::thread t([&] 
    cbToWrite = (lstrlen(lpvMessage) + 1) * sizeof(TCHAR);
    _tprintf(TEXT("Sending %d byte message: \"%s\"\n"), cbToWrite, lpvMessage);


    fSuccess = WriteFile(
        hPipe,                  // pipe handle
        lpvMessage,             // message
        cbToWrite,              // message length
        &cbWritten,             // bytes written
        NULL);                  // not overlapped

    if (!fSuccess)
    
        _tprintf(TEXT("WriteFile to pipe failed. GLE=%d\n"), GetLastError());
        return -1;
    

    printf("\nMessage sent to server, receiving reply as follows:\n");

);

while (1)   // main thread always reading

    do
    
        // Read from the pipe.

        fSuccess = ReadFile(
            hPipe,    // pipe handle
            chBuf,    // buffer to receive reply
            BUFSIZE * sizeof(TCHAR),  // size of buffer
            &cbRead,  // number of bytes read
            NULL);    // not overlapped

        if (!fSuccess && GetLastError() != ERROR_MORE_DATA)
            break;

        _tprintf(TEXT("\"%s\"\n"), chBuf);
     while (!fSuccess);  // repeat loop if ERROR_MORE_DATA

    if (!fSuccess)
    
        _tprintf(TEXT("ReadFile from pipe failed. GLE=%d\n"), GetLastError());
        return -1;
    



t.join();

我希望有人可以更正该代码以使其正常工作,或者您能说出标准做法或建议吗? 非常感谢!

【问题讨论】:

为什么是管道而不是套接字? 您想要异步 I/O 功能。所以并使用FILE_FLAG_OVERLAPPED 创建文件并使用异步io。在这种情况下,您可以并行发送/接收数据 如果您在非异步模式下创建文件,所有 I/O 操作都是安全的 - 新 I/O 直到旧 I/O 未完成才开始。所以写入操作将开始,直到读取完成。 "我想在 Windows 操作系统中编写一个命名管道客户端,即使客户端正在接收数据,它也可以随时发送数据" - 管道不是一个好的选择.数据通常一次只向一个方向流动,如果您尝试在两个方向上并行发送数据,您很容易使代码死锁。插座会是更好的选择,因为它是真正有方向性的。 如果你尝试在两个方向上并行发送数据,你可以很容易地死锁你的代码 - 使用异步双工管道,我们可以在两个方向上发送并且永远不会死锁 【参考方案1】:

来自CreateFile关于FILE_FLAG_OVERLAPPED的文档

如果指定了这个标志,文件可以用于同时 读写操作。

如果未指定此标志,则 I/O 操作将序列化

I/O 操作是序列化的,意味着新的 I/O 请求将一直等到前一个未完成。所以即使在这里使用多个线程也无济于事,如果你不使用FILE_FLAG_OVERLAPPED。例如,您可以从一个线程开始读取操作并等待数据不存在。如果您从另一个线程对此文件调用 write - write 将在 I/O 子系统代码中等待,直到您的读取未完成。即使您说查询文件名(通过GetFileInformationByHandleExFileNameInfo),此请求也会被序列化并等待您的读取未完成。

所以在创建文件时,同时 I/O 操作(不仅是读写,而且全部)的唯一选项使用FILE_FLAG_OVERLAPPED

【讨论】:

以上是关于如何在 Windows 中随时(同时)发送数据?的主要内容,如果未能解决你的问题,请参考以下文章

将二进制数据作为参数发送到 Web 服务中的方法?

同步和异步 各是啥啊。能举例说明吗?

excel发邮件问题

在 Windows 上根据给定优先级获取互斥锁

同时运行2个线程

Ruby on Rails如何在Windows 10中随时启动cron