您的位置:首页 > 运维架构 > Linux

linux下异步RPC的阶段性总结-非阻塞SOCKET客户端

2015-09-23 10:03 453 查看
尽可能使用非阻塞socket
int flags, s;
flags = fcntl (fd, F_GETFL, 0);
if (flags == -1){
close(fd);
return -1;
}

flags |= O_NONBLOCK;
s = fcntl (fd, F_SETFL, flags);
if (s == -1){
close(fd);
return -1;
}

使用效率高效的epoll机制获取多个socket上的IN/OUT事件

非阻塞socket连接服务端时,不一定立即连接得上服务器
通过判断connect函数的返回值和错误号做进一步跟踪
int ret = ::connect(this->fd, (struct sockaddr*)&(server_addr), sizeof(server_addr));
if(ret == 0){
this->on_connected();
}else if(ret < 0 && errno != EINPROGRESS){
//error
}else{
on_connecting();
}


IN/OUT事件时如果是connecting需要判断socket状态,socket reset发生时也会产生事件,然后才进入有效的读写

if(this->connect_status == 1){//connecting
int status = 0;
socklen_t slen;
if(getsockopt(this->fd, SOL_SOCKET, SO_ERROR, (void*)&status, &slen) < 0){
this->on_epollhup();
return;
}
if(status != 0){
this->on_epollhup();
return;
}

on_connected();
}


读写发生错误时,通过错误码判断是错误还是数据读完或者缓冲区满了,发生错误则按socket断开处理
错误代码包括:SIGPIP, EAGAIN 等, EAGAIN表示读完或者缓冲区满,等待下一次事件处理读或者写

为了达到更高的性能,epoll使用EPOLLET(边沿触发)机制,但是如果事件发生时,无数据可写时,下一次有数据时
则不会发生OUT事件,因此可以记录一个写空转标识write_nil_loop,epoll_wait事件之前判断是否有数据发送并且发生write_nil_loop,如果有,则重新登记epoll事件
if(worker->is_write_nil_loop() && (events & EPOLLOUT)){
epoll->remove(worker);
epoll->add(worker, events);
}else if(worker->get_events_mask() != events){
epoll->modify(worker, events);
}

同时,读取数据时,尽可能将数据读完,直到recv返回值-1,errno== EAGAIN,其他错误按照出错处理
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: