tcp socket客户端服务器和epoll以及mbuf

 需要一个简单的demo,客户端向服务器发送一张图片。
 乍一想,觉得是一个挺简单的需求,实际写的时候,需要考虑很多细节。
 指定一个简单的应用层协议,用于图片传输。简单一点,payload_len+payoad。其中payload_len,四字节长度,指示图片的大小。就是一个完整的报文有图片长度+图片内容组成。服务侧使用的socket采用non blocking模式。
 服务侧使用的socket采用non blocking模式,希望采用epoll对fd进行管理。问题出现,epoll中的ET和LT有什么区别?可以ref[1]。当然采用LT似乎简单一些,因为socket缓冲区中的数据没有一次读完,下次调用epoll_wait函数时,相对应的socket上仍会发生新的可读事件,可以继续读取。
 在ET模式下,那就需要一次把数据读完。否则,如果没有新的外部数据到来,对应的fd上就不会发生EPOLLIN事件。这里就需要循环读取:

                    if(events[i].events&EPOLLIN){
                        int n=0;
                        uint8_t buf[1500];
                        n=su_tcp_recv(con_fd,buf,1500);
                        if(n<=0){
                            std::cout<<"con close"<<std::endl;
                            su_socket_destroy(con_fd);
                            struct epoll_event ev;
                            epoll_ctl(epfd_, EPOLL_CTL_DEL, events[i].data.fd, &ev);
                        }
			auto it=clients_.find(con_fd);
                        if(n>0){
			   std::cout<<"in "<<n<<std::endl;
                            if(it!=clients_.end()){
                                it->second->OnNewData(buf,n);
                            }
                        }
			//data may not read all so, continue read, in ET mode
			for(;;){
				n=su_tcp_recv(con_fd,buf,1500);	
				if(n>0){
				std::cout<<"in "<<n<<std::endl;
                            	if(it!=clients_.end()){
                                	it->second->OnNewData(buf,n);
                            	}
				  std::cout<<" total "<<n<<std::endl;
				}else{
					std::cout<<" break "<<std::endl;
					break;
				}
			}
    }

 服务器侧如何获取客户端关闭连接事件呢(客户端调用close函数)?[2]有个ET的例子,但是针对的是http协议,服务侧获取一次数据,就断开与客户端的连接。我这个例子是要多次获取数据,是长连接。
 我发现,LT模式,在没有注册EPOLLRDHUP时,在EPOLLIN事件中,调用read函数,返回值为0,说明客户端断开连接。注册EPOLLRDHUP,就需要在EPOLLRDHUP中处理客户端端断开连接事件。而ET模式,必须注册EPOLLRDHUP,才能处理断开连接事件。
 代码测试LT模式,可在server.cc,line120中的注册事件,改成这样:

ev.events=EPOLLIN/*|EPOLLRDHUP|EPOLLET*/; 

 数据读取的缓冲区,采用mbuf。

struct mbuf {
    TAILQ_ENTRY(mbuf) next;
    uint8_t *pos;//read marker
    uint8_t *last;//write marker
    uint8_t *start;//start of buf
    uint8_t *end; //end of buf
    struct mhdr *queue; // the queue contain the buf
};
struct mbuf *mbuf_get(struct context *);
void mbuf_recycle(struct context *, struct mbuf *);
int mbuf_read_size(struct mbuf *);
int mbuf_write_size(struct mbuf *);
int mbuf_write(struct mbuf * mbuf,void *data,int len);
int mbuf_read(struct mbuf * mbuf,void*dst,int len);
int mbuf_peek(struct mbuf * mbuf,void*dst,int len);
bool mbuf_can_recycle(struct mbuf * mbuf);
bool mhdr_readable(struct mhdr *header);

 mbuf本身是free bad为socket缓冲区设计的结构。之前阅读ele的corvs[4]缓存代理时,觉得这个很有用,就摘下来了,改一改,用上了。
 代码url[5]
Ref:
[1] epoll中读写数据 的注意事项
[2] epoll et
[3] mbuf
[4] corvus
[5] tcp-learn

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值