使用重叠命名管道的服务器:如何将GetOverlappedResult()与ReadFile()一起使用?

时间:2011-04-01 22:06:12

标签: windows winapi named-pipes

我编写了一个使用重叠命名管道的服务器和客户端。我的问题主要是Readfile()和GetOverlappedResult()。

请注意,此程序是测试代码。它将在稍后的框架中集成(我将linux代码移植到使用AF_UNIX地址系列进行套接字连接的unix)

我描述了服务器部分。我有2个帖子:

1)主线程打开一个重叠的命名管道,然后遍历WaitForMultipleObjects()。 WaitForMultipleObjects()等待3个事件:第一个等待客户端连接。第二个允许我干净地退出程序。当ReadFile()中的操作挂起时,将发出第3个信号。

2)连接客户端时启动第二个线程。它遍历ReadFile()。

这是服务器代码:

http://pastebin.com/5rka7dK7

我主要使用MSDN doc(使用重叠I / O命名管道服务器,命名管道客户端),SDK和Internet上的其他doc来编写该代码。在[1]中查找客户端代码。客户端代码需要一些爱,但就目前而言,我专注于使服务器完美运行。

服务器代码中有4个函数(我忘记显示错误消息的函数):

a)svr_new:它创建重叠的命名管道和3个事件,并调用ConnectNamedPipe()

b)svr_del释放所有资源

c)_read_data_cb:调用ReadFile()

的线程

d)main()函数(主线程),它循环遍及WaitForMultipleObjects()

我的目标是在客户端断开连接时检测_read_data_cb()(ReadFile()失败并且GetLastError()返回ERROR_BROKEN_PIPE)以及数据来自客户端。

我不明白:

  • 我应该调用GetOverlappedResult()吗?
  • 如果是,在哪里?当ReadFile()失败并且GetLastError()返回ERROR_IO_PENDING(粘贴的第50行)时?当WaitForMultipleObjects()返回时(粘贴的第303行,我在那里注释了代码)?在其他地方?
  • 当WaitForMultipleObjects()返回时(粘贴的第302行),我执行ReadFile()事件的ResetEvent。这是一个正确的地方吗?

使用我粘贴的代码,如果客户端发送这24个字节(ReadFile()缓冲区大小为5个字节,则结果如下。我有意设置该值以测试客户端发送的数据大于ReadFile()缓冲区)

消息:“salut,c'est le client!”

输出:

$ ./server.exe 等待客户...... WaitForMultipleObjects:0 客户连接(1) WaitForMultipleObjects:2  * ReadFile:5 WaitForMultipleObjects:2  * ReadFile:5 WaitForMultipleObjects:2  * ReadFile:5 WaitForMultipleObjects:2  * ReadFile:5 WaitForMultipleObjects:2  * ReadFile:4

注意:WaitForMultipleObjects()可以被调用得少于它,它似乎是随机的。

所以,在我的代码中,我没有调用getOverlappedResult(),ReadFile()成功(il读取5 * 4 + 4 = 24字节),但我不知道读操作何时完成。

注意:我在ReadFile()失败时使用ERROR_IO_PENDING添加了printf(),无限期地调用了printf()。

此外,客户端发送2条消息。上面的那个,3秒后的另一个。永远不会读取第二条消息而ReadFile()因ERROR_SUCCESS错误而失败...(确切地说,ReadFile()返回FALSE,GetLastError()返回ERROR_SUCCESS)

所以,我完全迷失了。我在MSDN中的Internet代码(Server32.c和Client32.c)上搜索了几个小时。我仍然不知道在具体情况下该怎么做。

所以,有人解释我如何使用GetOverlappedResult()(如果我必须使用它)知道如何检查读取操作是否完成,以及在哪里?甚至,如果有人可以修复我的代码:-)我给了代码,以便每个人都可以测试它(我在互联网上找到很多文档,但它几乎总是不精确: - /)

谢谢

[1] http://pastebin.com/fbCH2By8

1 个答案:

答案 0 :(得分:1)

查看I / O完成端口。在我看来,这是接收和处理有关Windows中重叠操作的通知的最有效方式。因此,当您准备处理新的完成事件时,您将需要在阻塞和非阻塞模式下使用GetQueuedCompletionStatus和GetQueuedCompletionStatusEx,而不是不时调用GetOverlappedResult。事实上,你甚至可以完全摆脱WaitForMultipleObjects。

另外,您定位的是哪种Unix风格?在Solaris中有一个非常相似的抽象。看看man port_create。

不幸的是,Linux中没有类似的东西。信号(包括实时)可以在某种程度上用作可等待的完成对象,但它们不像Windows和Solaris中的端口那样全面。