前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Tars-C++ 揭秘篇:文件描述符处理“套路”

Tars-C++ 揭秘篇:文件描述符处理“套路”

原创
作者头像
路小饭
修改2019-03-06 10:42:55
8910
修改2019-03-06 10:42:55
举报

本章总结Tars中对文件描述符进行操作时的一些“套路”的做法,偏重异常时候的处理。这些处理方式在任何RPC框架中都是值得考虑的

1、bind

  • 进行bind操作前,设置服务器可以快速二次启动而不用等待一段时间:
代码语言:txt
复制
    int iReuseAddr = 1;

    //设置
    setSockOpt(SO_REUSEADDR, (const void *)&iReuseAddr, sizeof(int), SOL_SOCKET);
  • ::bind()返回值小于0时候,终止应用程序

2、listen

  • ::listen()返回值小于0时候,终止应用程序
  • 设置keepalive
代码语言:javascript
复制
    int flag = 1;
    if(setSockOpt(SO_KEEPALIVE, (char*)&flag, int(sizeof(int)), SOL_SOCKET) == -1)
    {
        throw TC_Socket_Exception("[TC_Socket::setKeepAlive] error", errno);
    }
  • 设置tcpNoDelay
代码语言:javascript
复制
    int flag = 1;

    if(setSockOpt(TCP_NODELAY, (char*)&flag, int(sizeof(int)), IPPROTO_TCP) == -1)
    {
        throw TC_Socket_Exception("[TC_Socket::setTcpNoDelay] error", errno);
    }
  • 设置noCloseWait
代码语言:javascript
复制
    linger stLinger;
    stLinger.l_onoff = 1;  //在close socket调用后, 但是还有数据没发送完毕的时候容许逗留
    stLinger.l_linger = 0; //容许逗留的时间为0秒

    if(setSockOpt(SO_LINGER, (const void *)&stLinger, sizeof(linger), SOL_SOCKET) == -1)
    {
        throw TC_Socket_Exception("[TC_Socket::setNoCloseWait] error", errno);
    }
  • 设置noblock
代码语言:javascript
复制
void TC_Socket::setblock(int fd, bool bBlock)
{
    int val = 0;

    if ((val = fcntl(fd, F_GETFL, 0)) == -1)
    {
        throw TC_Socket_Exception("[TC_Socket::setblock] fcntl [F_GETFL] error", errno);
    }

    if(!bBlock)
    {
        val |= O_NONBLOCK;
    }
    else
    {
        val &= ~O_NONBLOCK;
    }

    if (fcntl(fd, F_SETFL, val) == -1)
    {
        throw TC_Socket_Exception("[TC_Socket::setblock] fcntl [F_SETFL] error", errno);
    }
}

3、accept

  • 获取accept描述符
代码语言:javascript
复制
    while ((ifd = ::accept(_sock, pstSockAddr, &iSockLen)) < 0 && errno == EINTR);
  • 当上面ifd不大于0时候
代码语言:javascript
复制
if(errno == EAGAIN)
//跳出外层循环accept操作

4、epoll

  • 遇到EPOLLERR 和 EPOLLHUP,应当把描述符从epoll中删除,同时调用close清理描述符
代码语言:javascript
复制
    if (ev.events & EPOLLERR || ev.events & EPOLLHUP)
         //把描述符从epoll中删除,同时调用close清理描述符
  • EPOLLIN读取数据时候
代码语言:javascript
复制
    while(true)
    {
        char buffer[32 * 1024];
        int iBytesReceived = 0;
        iBytesReceived = ::read(_sock.getfd(), (void*)buffer, sizeof(buffer));
        if (iBytesReceived < 0)
        {
            if(errno == EAGAIN)
            {
                //没有数据了
                break;
            }
            else
            {
                //客户端主动关闭
                //把描述符从epoll中删除,同时调用close清理描述符
            }
        }
        else if( iBytesReceived == 0)
        {
           //把描述符从epoll中删除,同时调用close清理描述符
        }
    }
  • EPOLLOUT发送数据时候
代码语言:javascript
复制
    int bytes = static_cast<int>(::writev(sock, &buffers[0], cnt));
    if (bytes == -1)
    {
        assert (errno != EINVAL);
        if (errno == EAGAIN)
            return 0;

        //把描述符从epoll中删除,同时调用close清理描述符
    }
代码语言:javascript
复制
    int bytes = ::send(_sock.getfd(), data, len, 0);
    if (bytes == -1)
    {
        if (EAGAIN == errno)
            bytes = 0; 
                      
        if (EINTR == errno)
            bytes = 0; // try ::send later
            
        //把描述符从epoll中删除,同时调用close清理描述符
    }

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、bind
  • 2、listen
  • 3、accept
  • 4、epoll
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档