我正在使用select()
和NONBLOCKING
连接fd来接受连接并处理输入和输出。我有一些问题处理大于缓冲区大小的大数据传输。例如这里:
readCount = 1;
while(readCount > 0)
{
// clear t_input to read new data from the fd
memset(t_input, 0, CLIENT_INPUT_BUFF_LEN);
// read data from the client connectionFd and since t_input is 1024 only
// read that much
readCount = read(iter->connectionFd, t_input, 1024);
printf("<<< %d - %s >>> \n", errno, strerror(errno));
if(readCount == -1)
{
if( errno == EAGAIN)
break;
}
iter->AppendInputData(t_input, readCount);
}
这对大数据不起作用。因此,当我传输的数据小于1024
时,第一个read
调用成功完成,数据将在AppendInputData
调用中复制。由于它处于循环中,第二个read
调用返回-1
,并将errno
设置为EAGAIN
然后打破循环 - 这一切都适用于此情况。
但是,如果数据大于1024
,则第二次读取调用将再次失败,errno
将设置为EAGAIN
。奇怪的是,在调试模式下,我没有看到这种行为,第二次或第三次read
调用返回正常,所有数据都被收集。有人可以解释可能发生的事情吗?
答案 0 :(得分:2)
这是时机。您无法假设所有数据都会连续到达,并且只要您调用read(),或者当EAGAIN发生时,它将永远存在。习惯上调用select()告诉您何时可以读取数据。
您在调试模式下会遇到不同的行为,因为您正在改变时间。
答案 1 :(得分:2)
尝试更像这样的东西:
do
{
// read data from the client connectionFd and since t_input is 1024 only read that much
readCount = read(iter->connectionFd, t_input, 1024);
if (readCount == -1)
{
if (errno == EAGAIN)
{
fd_set fd;
FD_ZERO(&fd);
FD_SET(iter->connectionFd, &fd);
timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
readCount = select(iter->connectionFd+1, &fd, NULL, NULL, &tv);
if (readCount == 1)
continue;
if (readCount == 0)
{
printf("<<< timeout >>> \n");
break;
}
}
printf("<<< %d - %s >>> \n", errno, strerror(errno));
break;
}
if (readCount == 0)
{
printf("<<< disconnect >>> \n");
break;
}
iter->AppendInputData(t_input, readCount);
}
while (true);