【问题标题】:C 'recv' with MSG_PEEK doesn't return -1带有 MSG_PEEK 的 C 'recv' 不返回 -1
【发布时间】:2012-08-21 07:38:58
【问题描述】:

我正在编写一个 C 函数来检查来自客户端的套接字连接是否可用。我使用带有 MSG_PEEK 的“recv”函数来不改变输入缓冲区。

但是,当客户端关闭套接字连接时,'recv' 应该返回 -1,但事实并非如此。客户端关闭后,下面函数中的'recv'一直返回0。

char is_avail(int connection) {
  char buffer;

  int result = recv(connection,&buffer,1,MSG_PEEK);
  if (result<0)
    return 0;
  else
    return 1;
}

这件事有什么理由吗?我还想将 MSG_PEEK 与 MSG_WAITALL 结合起来。我试过了:

recv(connection,&buffer,1,MSG_PEEK|MSG_WAITALL);

但是没有生效。

【问题讨论】:

  • 检查来自客户端的套接字连接是否可用你在调用listen的套接字上调用recv
  • 不要使用MSG_WAITALL,因为它会阻塞直到它可以满足您的请求。所以它会一直阻塞,直到有数据要读取(或在你的情况下偷看),理论上这可能是永远的。
  • @JoachimPileborg 实际上,recv 已经默认执行此操作,除非套接字设置为“非阻塞”。无论如何,MSG_WAITALL 在这种情况下毫无意义,因为它会等到可以读取 1 个字节...这等于它在没有 MSG_WAITALL 的情况下等待的字节数。
  • MSG_PEEK 和一般的 isAvailable 从套接字检查是一个坏主意。它在 Winsock 程序员跛脚名单中赢得了一席之地——因为它天生不可靠。不要使用 PEEK,只需立即将所有数据复制到自己的缓冲区。
  • @kert 很老的评论.. 但是,我目前正在考虑将协议从固定大小的缓冲区更改为动态大小的消息,并且会对 MSG_PEEK 的任何优点/缺点感兴趣,你知道任何资源吗关于这个话题?

标签: c++ c sockets recv peek


【解决方案1】:

当套接字正确关闭时,recv 不返回 -1,而是返回 '0'。

0 -> 优雅地关闭套接字

-1-> 发生了实际错误

> 0-> 数据已被读取。

【讨论】:

  • @PaulDinh 不,它没有。如果没有要读取的数据,则根本不返回。它阻塞,直到有数据要读取。一个例外:当您将套接字设置为非阻塞时。在这种情况下,如果没有数据,recv 将返回 -1。 recv 唯一返回“0”的时间是连接实际关闭的时候。
  • 我的socket是非阻塞的,我用fcntl(socket,F_SETFL,O_NONBLOCK);设置它,但是'recv'返回0,还是异常
  • @PaulDinh 您是否尝试过使用 Wireshark 检查连接是否已正确建立并且在此期间没有再次断开?插座是连接的,对吧?毕竟'0'表示'关闭连接'。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-14
  • 2011-04-09
相关资源
最近更新 更多