【问题标题】:Use select on pipe returns 10038在管道上使用选择返回 10038
【发布时间】:2016-10-26 19:39:07
【问题描述】:

我的管道有问题。我正在使用::_pipe 函数创建管道并希望在其上使用selectWSAGetLastError 返回10038 并且kua 是-1。这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <Winsock2.h>
#include <Windows.h>
#include <Winbase.h>
#include <FileAPI.h>
#include <io.h>
#include <wchar.h>

int main()
{
  WORD wVersionRequested;
  wVersionRequested = MAKEWORD(2, 2);
  WSADATA wsaData;

  WSAStartup(wVersionRequested, &wsaData);
  int fd[2];
  _pipe(&fd[2], 65536, 0);
  FD_SET set;

  FD_SET((unsigned int) (fd[0]), (&set));

  timeval time;
  time.tv_sec = 1;
  time.tv_usec = 0;
  int kua = select(0, &set, NULL, NULL, &time);
  printf("last ->%d\n",  WSAGetLastError());
  fflush(stdout);
  }

请不要注意标题,我读过一些有相同错误的主题,但没有一个是这样的(管道以这种方式创建)。希望你能帮忙。谢谢。

编辑 我现在稍微更改了代码_pipe(fd, 65536, 0);,但在这种情况下它给了我段错误。

【问题讨论】:

  • 来自文档:select 函数返回准备就绪并包含在 fd_set 结构中的套接字句柄的总数,如果时间限制过期,则返回零,如果发生错误,则返回 SOCKET_ERROR。如果返回值为 SOCKET_ERROR,则可以使用 WSAGetLastError 来检索特定的错误代码。 您没有检查返回值。为什么不呢?
  • 对不起,我现在检查了,它的 -1 我会编辑
  • 另外,fd[2] 不在数组末尾,因此您正在破坏堆栈。您甚至可以通过管道进行选择吗?
  • 您在调用_pipe 时也不会检查错误。真的不是一个很好的节目。没有错误检查、堆栈损坏和几乎无法更清晰的错误代码。系统告诉您您正在传递不是套接字的东西。显而易见的结论:管道不是套接字。你认为 10038 是什么意思?
  • 您是否考虑过查找 Winsock 错误 10038?

标签: c winapi error-handling pipe


【解决方案1】:

在大多数平台上,管道和套接字都使用文件描述符表示,因此两者都可以与对文件描述符进行操作的文件 I/O 函数一起使用,包括 select()

但是,在 Windows 上,套接字和管道是不同的对象类型,根本不使用文件描述符来表示。 select() 只支持套接字,不支持文件或管道。这就是为什么您收到错误 10038,又名 WSAENOTSOCK

对非套接字的套接字操作。
尝试对非套接字的操作。套接字句柄参数没有引用有效的套接字,或者对于 select,fd_set 的成员无效。

对于由_pipe() 创建的管道对象,没有等效的select()。你所能做的就是读写。

如果您需要在读取数据之前检测数据何时到达管道,请使用CreatePipe()PeekNamedPipe() 而不是_pipe()。否则,请考虑改用重叠 I/O 或 I/O 完成端口。这将允许您在后台启动异步读取操作,并让它在收到数据时通知您。

【讨论】:

  • 请教一个问题:我可以在 _pipe 创建的管道上进行非阻塞读取吗?
  • @Rasty 在 Linux 上,是的,使用 pipe()O_NONBLOCKO_ASYNC 标志。但在 Windows 上,AFAIK _pipe() 不支持这些标志。改用 Win32 管道,就像我之前建议的那样。
猜你喜欢
  • 2021-01-22
  • 2014-01-24
  • 1970-01-01
  • 2017-04-26
  • 1970-01-01
  • 2011-07-15
  • 1970-01-01
  • 2018-12-17
  • 1970-01-01
相关资源
最近更新 更多