本人刚学习epoll,向论坛大神问几个问题
本人理解,ET只有在文件描述符未就绪变为就绪时才会重新通过内核来告知,导致每一次的读取必须将缓冲区内数据读完,即处理完该事件
但是我们自己设定的用户空间缓冲区buf是有大小的,假如小于sockfd通告窗口大小,还是说我们会一般将用户空间的buf大小就写成和通告的窗口大小写成一致,则不存在,一次无法将缓冲区读完的情况发生
以下是tcp回射程序的部分
else if(events[i].events&EPOLLIN)
{
if((sockfd=events[i].data.fd)<0)
continue;
while(rs)
{
if((n=read(sockfd,buf,MAXLINE))<0)
{
if(errno==ECONNRESET||errno=EAGAIN)
{
close(sockfd);
events[i].data.fd=-1;
}
else if(n==0)
{
close(sockfd);
events[i].data.fd=-1;
}
}
if(n==sizeof(buf))
rs=1;
else
rs=0;
}
ev.data.fd=sockfd;
ev.events=EPOLLOUT|EPOLLET;
epoll_ctl(efd,EPOLL_CTL_MOD,sockfd,&ev);
}
如何一直读sockfd,这是本人自己理解的 epoll但由于一直没有用epoll将该sockfd改成写,无法将buf内的数据写到sockfd,如何改正,或者如何正确的写出epoll函数,
我在网上找了很多种实现epoll的都并没有持续读直到无法读取那一部分的代码。一直不理解epoll如何实现这一过程,同理write过程也有这样一个问题,(若没写完buf内的内容必须持续写),但后面写的部分由于无法读取会覆盖前面写的部分,可能问题有些混乱,谢谢各位大神
1、tcp缓存区是内核管理的
2、读取到没有缓存区的方法是将sockfd设置成非阻塞,然后循环读取直到返回无数据或者是超时错误。若需要持续读取数据则将sockfd再次放入epoll监听
3、数据可能读不完整是需求靠应用层协议实现
系统内部读写是两个缓冲区,没有读直接写也不会影响数据
读的话可以把socket设置成非阻塞,循环读直到没有数据为止。也可以在message里设置一个包长,根据包长来收数据,就算没读完也是下个包粘包了
epoll触发的时候,数据是放在内核的,通过read 把内核的buffer复制到应用层。
那么应用层buffer比内核buffer小的时候,应用层就一直循环读啊,读到socket返回 EWOULDBLOCK的错误就读完了。然后继续epoll_wait。
不知道有没有回答到你的点。
封装一个读取函数,循环读取:
__Read(int iFd)
{
char buf[10224];//可以更大
ssize_t lsize = 0;
lsize = recv(iFd, buf, 1024, MSG_DONTWAIT);
while(lsize > 0)
{
/* doth by readed buf */
...
...
lsize = recv(iFd, buf, 1024, MSG_DONTWAIT)
}
}