C++函数选择显示在读取后的STDIN中有数据

C++函数选择显示在读取后的STDIN中有数据,c++,select,stdin,C++,Select,Stdin,我的聊天客户端中有以下代码: fd_set fds; struct timeval t; t.tv_sec = 0; t.tv_usec = 100; int ret; string message; while(run) { FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); if((ret = select(STDIN_FILENO + 1, &fds, NULL, NULL, &t)) <

我的聊天客户端中有以下代码:

fd_set fds;
struct timeval t;
t.tv_sec = 0;
t.tv_usec = 100;
int ret;

string message;

while(run)
{
    FD_ZERO(&fds);
    FD_SET(STDIN_FILENO, &fds);

    if((ret = select(STDIN_FILENO + 1, &fds, NULL, NULL, &t)) < 0)
    {
        exit(ERR_SELECT);
    }
    else if(ret > 0 && FD_ISSET(STDIN_FILENO, &fds))
    {
        message.clear();
        getline(cin, message);

        if(strlen(message.c_str()) > 0)
        {
            send_message(&message, client_socket);
        }
    }
}
或者这个:

printf "message\n" | ./chat_client
它读取并发送消息,但在循环的下一个迭代中,它的行为类似于stdin中的内容,但getline只读取空字符串。然后当我写东西时,getline不会读它

有人知道是什么原因吗

感谢您提供的任何建议

如果到达文件末尾,则返回,这是在读取了来自管道的所有内容后发生的。您需要显式测试cin.eof是否返回true

至于select,它的设计是,如果在文件末尾,它会将文件显示为可读的。这样程序就可以检测到连接已关闭。Linux声明:

如果可以执行 相应的I/O操作,如read2无阻塞

在EOF读取文件描述符时,返回零而不阻塞

我不确定通过istream在fd读取上选择是否会出现问题,但这对我Linux/gcc有效:

#include <iostream>
#include <sys/select.h>
#include <unistd.h>

int main()
{
  std::string message;
  while(1) {
    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(STDIN_FILENO, &fds);
    int ret = select(1, &fds, NULL, NULL, NULL);
    if (ret == -1) break;
    getline(std::cin, message);
    if (std::cin.eof()) {
      std::cout << "eof." << std::endl;
      break;
    }
    std::cout << "read: " << message << std::endl;
  }
  return 0; 
}

你使用C还是C++?没有C++ C++语言这样的语言,只使用函数GECHCHAR代替GETLIN,读取到EOF,在主循环的每次迭代中仍然是相同的,GECHAR返回EOF。你能写下我应该在哪里测试cin.eof吗?或者,我如何使它读取整个标准输入,然后再次等待下一次输入?当我读取输入且cin.eof为true但我想再次读取时,我如何使cin再次可读。因为cin.eof在getline之后返回true,但我无法再次从cin读取。@Spook,在您已经阅读到最后之后,您打算阅读什么?使用您给出的命令:echo foo |./prog,来自标准输入的所有内容都是echo输出的字符串。没有别的东西可读了。因为它是一个管道,所以你甚至不能向后搜索它。好吧,如果我从输入端发送消息,如果它只以“\n”结尾,并且有人运行命令:echo message1\n message2 |/prog,我只能发送message1并结束整个程序。程序运行时,用户无法写入新消息。是正确的吗?@Spook,您当然可以打开另一个文件或从终端显式读取,而不必考虑重定向的stdin。但这是一个有点不同的问题。不过,您也可以让用户指定一些内容作为命令行参数,然后从stdin中读取其他内容。但是,我认为这并不是直接相关的。
#include <iostream>
#include <sys/select.h>
#include <unistd.h>

int main()
{
  std::string message;
  while(1) {
    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(STDIN_FILENO, &fds);
    int ret = select(1, &fds, NULL, NULL, NULL);
    if (ret == -1) break;
    getline(std::cin, message);
    if (std::cin.eof()) {
      std::cout << "eof." << std::endl;
      break;
    }
    std::cout << "read: " << message << std::endl;
  }
  return 0; 
}