【利用C++ RAII机制】实现Hello World服务器

写一个服务器程序

写一个简单的服务器,客户端链接服务器之后,服务器给其发一个Hello World之后,中断服务器和客户端的链接。

写c++的时候,尤其是服务器开发会对异常情况作处理。

int main_codeblock_if() {
    ...
    int ret = listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == ret)
    {
        log(socket());
        close(listenfd);
        exit(-100);
    }
	...
    //socket 2
    ret = bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
    if(-1 == ret)
    {
        log(bind());
        close(listenfd);
        exit(-100);
    }
	...
    //socket 3
    ret = listen(listenfd, 20);
    if(-1 == ret)
    {
        log(listen());
        close(listenfd);
        exit(-100);
    }
    ...
}

常见的场景还比如:

void codeBlock1()
{
    char *string = new char[1024];

    if(condition1)
    {
        delete [] string;
        string = nullptr;
    }
    if(condition2)
    {
        delete [] string;
        string = nullptr;
    }

    if(condition3)
    {
        delete [] string;
        string = nullptr;
    }

    delete [] string;
    string = nullptr;
}

可以概括为:先分配资源,在进行相关操作,在中间步骤中出错,对相应的资源进行回收
在资源回收很容易忘掉,或者没有执行到其中(逻辑分支不能达到,抛出异常),造成内存泄漏。有没有方法避免这种情况?C++ RAII机制可以供我们使用

RAII 防止内存泄漏

RAII即资源获取就是初始化我们拿到资源的时候直接使用就可以了,跳过初始化,析构(资源回收)的步骤。原理上是使用栈内变量离开自己的作用域之后,自动释放掉资源的性质。
一开始我不知怎么设计这个类,看了书上封装之后的用法,明白了。


{
Socket_RAII socket;
if(false == socket.init()) 	return -1;
if(false == socket.bind()) 	return -1;
if(false == socket.listen()) 	return -1;
soket.work();
}

//离开 之后sobket 自动被释放掉

服务器代码





int main()
{
    {
        socket_RAII socket;

        if(false == socket.socket_init())
        {
            return -1;
        }

        if(false == socket.socket_bind("127.0.0.1",2333))
        {
            return -1;
        }

        if(false == socket.socket_listen(20))
        {
            return -1;
        }


        socket.work();

    }

}
class socket_RAII {
public:

    bool socket_init()
    {
        memset(&serveraddr,0,sizeof (serveraddr));
        m_listenfd = socket(AF_INET,SOCK_STREAM,0);


        if(-1 == m_listenfd)
        {
            //   logger
//            assert(-1 != m_listenfd);
            return false;
        }
        return true;
    }

     bool socket_bind(string ip,int port) {

        in_addr addr;
        int res = inet_aton(ip.c_str(),&addr);

        if(0 == res)
        {
//            log ip convert error
            return false;
        }

        serveraddr.sin_family = AF_INET;
        serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
        serveraddr.sin_port = htons(port);

        socklen_t len = sizeof(serveraddr);
        int ret = bind(m_listenfd, (struct sockaddr *) &serveraddr,len );


        if(-1 == ret)
        {
            return false;
        }
        return true;
    }

     bool socket_listen(int value)
    {
        int ret = listen(m_listenfd, value);

        if(-1 == ret)
        {
            return false;
        }
        return true;

    }
    void work()
    {
       do {
            sockaddr_in cliaddr;
            memset(&cliaddr,0,sizeof (cliaddr));
            socklen_t cliaddr_len = sizeof(cliaddr);

            int connfd = accept(m_listenfd, (sockaddr *) &cliaddr, &cliaddr_len);
            assert (-1 != connfd);
            printf("connfd: %d Client IP: %s Port %d \n", connfd, inet_ntoa(cliaddr.sin_addr),
                   ntohs(cliaddr.sin_port));

            //async_do_work_struct(connfd);
            sync_do_work(connfd);
        } while(0);

    }
private:
    void sync_do_work(int fd) {
        char writeBuffer[1024] = {'\0'};
        std::sprintf(writeBuffer, "%s", "hello world \n");
        int byteNum = send(fd, writeBuffer, strlen(writeBuffer), 0);
        close(fd);
    }
public:
    socket_RAII()
    {
        m_listenfd = -1;
    }

    ~socket_RAII()
    {
        if(-1 != m_listenfd ) close(m_listenfd);

        cout << "~socket_RAII()" << endl;
    }

private:

    int m_listenfd;
    sockaddr_in serveraddr;

};




客户端代码


int main() {


    in_addr addr;
    int res = inet_aton("192.168.1.1",&addr);

    //socket 1
    int clientfd = 0;
    int ret = clientfd = socket(AF_INET, SOCK_STREAM, 0);
    assert(-1 != ret);

    struct sockaddr_in servaddr, cliaddr;

    int port = 2333;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(port);
    socklen_t seraddr_len = sizeof(servaddr);
     ret  = connect(clientfd,(sockaddr *) &servaddr,seraddr_len);

     while(1)
     {
         char readBuffer[1024] = {'\0'};
         int bytenum = recv(clientfd,readBuffer,sizeof (readBuffer),0);
         if(0 == bytenum)
         {
             printf("%s","client shut down.\n");
             break;
         }
         printf("%s",readBuffer);

     }


    close(clientfd);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值