C++ - 函数 select 显示读取后标准输入中有数据
C++ - function select shows there are data in stdin after they were read
我的聊天客户端中有以下代码:
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);
}
}
}
当我在程序 运行 中输入内容时,它工作正常。它读取 stdin 中的消息,发送它,然后循环等待下一个输入。但是当我像这样开始将输入传递给程序时:
echo "message" | ./chat_client
或者这样:
printf "message\n" | ./chat_client
它读取并发送 "message" 但随后在循环的下一次迭代中它的行为就像标准输入中有内容但 getline
只读取空字符串。然后当我写东西时,getline
不读它。
有人知道是什么原因造成的吗?
感谢任何建议
getline()
returns 如果它到达文件末尾,这发生在所有来自管道的内容都已被读取时。您需要明确测试 cin.eof()
returns 是否为真。
至于 select()
它是设计使然,如果在文件末尾,它会将文件显示为 "readable"。这样程序可以检测到连接已关闭。 Linux manual for select()
指出:
A file descriptor is considered ready if it is possible to perform a
corresponding I/O operation (e.g., read(2) without blocking...
和文件描述符上的 read()
在 EOF returns 一个没有阻塞的零。
我不确定通过 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;
}
我的聊天客户端中有以下代码:
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);
}
}
}
当我在程序 运行 中输入内容时,它工作正常。它读取 stdin 中的消息,发送它,然后循环等待下一个输入。但是当我像这样开始将输入传递给程序时:
echo "message" | ./chat_client
或者这样:
printf "message\n" | ./chat_client
它读取并发送 "message" 但随后在循环的下一次迭代中它的行为就像标准输入中有内容但 getline
只读取空字符串。然后当我写东西时,getline
不读它。
有人知道是什么原因造成的吗?
感谢任何建议
getline()
returns 如果它到达文件末尾,这发生在所有来自管道的内容都已被读取时。您需要明确测试 cin.eof()
returns 是否为真。
至于 select()
它是设计使然,如果在文件末尾,它会将文件显示为 "readable"。这样程序可以检测到连接已关闭。 Linux manual for select()
指出:
A file descriptor is considered ready if it is possible to perform a corresponding I/O operation (e.g., read(2) without blocking...
和文件描述符上的 read()
在 EOF returns 一个没有阻塞的零。
我不确定通过 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;
}