Linux、C、epoll()、read()数据未完成?
Linux, C, epoll(), read() data incompleted?
Linux, C. 只有使用 epoll() 才会出现以下问题。如果我在服务器套接字上使用 select() ,则不会丢失数据。
===============================
更新:
我在 read() 中收到 errno =11(再试一次)。
我需要继续还是中断 while 循环?
===============================
我有客户端,分10次发送1280K数据(每次发送128K数据);
我有服务器端,使用 epoll() 来观察传入的数据。
收到通知后,我使用以下代码读取数据:
nbytes = Nread(current_fd, buffer, bytes_to_be_read);
int Nread(int fd, char *buffer, size_t count)
{
ssize_t r;
size_t left = count;
printf("===>\n");
while (left > 0){
r = read(fd, buffer, left);
printf("data: %ld\n", r);
if (r < 1) {
printf("errno: %d\n", errno);
break; //I do received 2 errors of Try Again. How to try again?
}
left -= r;
buffer += r;
}
printf("=> done, %ld\n", total - left);
return count - left;
}
在 Nread 中,我希望读取 bytes_to_be_read (65536) 个字节和 return.
但是,当运行这个工具时,我发现服务器端只是收到这样的东西。看起来在某些情况下我没有从缓冲区读取所有数据。为什么?
1===>
data: 65536
=> done, 65536
2===>
data: 65536
=> done, 65536
3===>
data: 60734
data: 4802
=> done, 65536
4===>
data: 55934
data: -1
errno: 11
=> done, 55934 //data is not enough. the missing part should come soon. but why I am not notified?
5===>
data: 60736
data: 4800
=> done, 65536
6===>
data: 65536
=> done, 65536
7===>
data: 65536
=> done, 65536
8===>
data: 65536
=> done, 65536
9===>
data: 65536
=> done, 65536
10===>
data: 65536
=> done, 65536
11===>
data: 65536
=> done, 65536
12===>
data: 65536
=> done, 65536
13===>
data: 65536
=> done, 65536
14===>
data: 65536
=> done, 65536
15===>
data: 65536
=> done, 65536
16===>
data: 65536
=> done, 65536
17===>
data: 65536
=> done, 65536
18===>
data: 65536
=> done, 65536
19===>
data: 65536
=> done, 65536
===============
更新:
如果我使用这段代码读取所有数据,则不会丢失字节。但表现不佳:
36 int read_all(int fd, char *buffer)
37 {
38 ssize_t count = 0, bytes = 0;
39
40 while(1){
41 bytes = read(fd, buffer, sizeof(buffer));
42 if (bytes < 1)
43 break;
44 count += bytes;
45 }
46 return count;
47 }
===================================
EPOLL()
efd = epoll_create1 (0);
event.data.fd = listener_fd;
event.events = EPOLLIN | EPOLLET;
epoll_ctl(efd, EPOLL_CTL_ADD, listener_fd, &event);
while (1){
n_fds = epoll_wait (efd, events, MAX_EPOLL_EVENTS, -1);
for (i = 0; i < n_fds; i++){
...........
if (islistener) {
.....
//handle new connections
}
else{
bzero(buffer, recv_buf_size);
if ((n= Nread(fd, buffer, recv_buf_size)) <= 0) {
//error
}
else
{
//add bytes to total:
__sync_fetch_and_add(&(mythreads->total_bytes_transferred), n) ;
}
}
break; //I do received 2 errors of Try Again. How to try again?
回到你的 epoll 循环。
data: 60734 //??? why I am not able to read all 65536 bytes?
因为还没有收到。
我认为您可能错过了关于如何使用 epoll
实现非阻塞 I/O 的大局。
epoll
有数据时告诉你。
- 那时候你能读多少就读多少。
- 你回到第 1 步。
event.events = EPOLLIN | EPOLLET;
您正在进行边沿触发轮询。这意味着您最后一次阅读可能没有阅读所有可用数据。它在读取 64k 数据后停止,即使有更多数据可用。但是由于边缘触发,轮询不会再次触发。建议删除 EPOLLET
.
Linux, C. 只有使用 epoll() 才会出现以下问题。如果我在服务器套接字上使用 select() ,则不会丢失数据。
===============================
更新: 我在 read() 中收到 errno =11(再试一次)。 我需要继续还是中断 while 循环?
===============================
我有客户端,分10次发送1280K数据(每次发送128K数据);
我有服务器端,使用 epoll() 来观察传入的数据。
收到通知后,我使用以下代码读取数据:
nbytes = Nread(current_fd, buffer, bytes_to_be_read);
int Nread(int fd, char *buffer, size_t count)
{
ssize_t r;
size_t left = count;
printf("===>\n");
while (left > 0){
r = read(fd, buffer, left);
printf("data: %ld\n", r);
if (r < 1) {
printf("errno: %d\n", errno);
break; //I do received 2 errors of Try Again. How to try again?
}
left -= r;
buffer += r;
}
printf("=> done, %ld\n", total - left);
return count - left;
}
在 Nread 中,我希望读取 bytes_to_be_read (65536) 个字节和 return.
但是,当运行这个工具时,我发现服务器端只是收到这样的东西。看起来在某些情况下我没有从缓冲区读取所有数据。为什么?
1===>
data: 65536
=> done, 65536
2===>
data: 65536
=> done, 65536
3===>
data: 60734
data: 4802
=> done, 65536
4===>
data: 55934
data: -1
errno: 11
=> done, 55934 //data is not enough. the missing part should come soon. but why I am not notified?
5===>
data: 60736
data: 4800
=> done, 65536
6===>
data: 65536
=> done, 65536
7===>
data: 65536
=> done, 65536
8===>
data: 65536
=> done, 65536
9===>
data: 65536
=> done, 65536
10===>
data: 65536
=> done, 65536
11===>
data: 65536
=> done, 65536
12===>
data: 65536
=> done, 65536
13===>
data: 65536
=> done, 65536
14===>
data: 65536
=> done, 65536
15===>
data: 65536
=> done, 65536
16===>
data: 65536
=> done, 65536
17===>
data: 65536
=> done, 65536
18===>
data: 65536
=> done, 65536
19===>
data: 65536
=> done, 65536
===============
更新:
如果我使用这段代码读取所有数据,则不会丢失字节。但表现不佳:
36 int read_all(int fd, char *buffer)
37 {
38 ssize_t count = 0, bytes = 0;
39
40 while(1){
41 bytes = read(fd, buffer, sizeof(buffer));
42 if (bytes < 1)
43 break;
44 count += bytes;
45 }
46 return count;
47 }
===================================
EPOLL()
efd = epoll_create1 (0);
event.data.fd = listener_fd;
event.events = EPOLLIN | EPOLLET;
epoll_ctl(efd, EPOLL_CTL_ADD, listener_fd, &event);
while (1){
n_fds = epoll_wait (efd, events, MAX_EPOLL_EVENTS, -1);
for (i = 0; i < n_fds; i++){
...........
if (islistener) {
.....
//handle new connections
}
else{
bzero(buffer, recv_buf_size);
if ((n= Nread(fd, buffer, recv_buf_size)) <= 0) {
//error
}
else
{
//add bytes to total:
__sync_fetch_and_add(&(mythreads->total_bytes_transferred), n) ;
}
}
break; //I do received 2 errors of Try Again. How to try again?
回到你的 epoll 循环。
data: 60734 //??? why I am not able to read all 65536 bytes?
因为还没有收到。
我认为您可能错过了关于如何使用 epoll
实现非阻塞 I/O 的大局。
epoll
有数据时告诉你。- 那时候你能读多少就读多少。
- 你回到第 1 步。
event.events = EPOLLIN | EPOLLET;
您正在进行边沿触发轮询。这意味着您最后一次阅读可能没有阅读所有可用数据。它在读取 64k 数据后停止,即使有更多数据可用。但是由于边缘触发,轮询不会再次触发。建议删除 EPOLLET
.