LINUX网络编程:Tcpsocket封装

目录

1.使用Tcp套接字的流程

2.模板方法设计模式

3.socket.hpp

1.搭建抽象类的算法框架

2.具体类算法实现

2.1创建套接字

2.2绑定

2.3套接字设为监听

2.4接收链接

2.5客户端连接服务器


在使用Tcp套接字时,很多的流程都是固定的,将这些固定的流程封装,更方便后续的使用。

1.使用Tcp套接字的流程

1.创建套接字

2.与网络的信息进行绑定,如ip,端口号

3.将套接字的状态设为监听

4.接收客户端链接

5.进行业务处理

将以上流程都使用面向对象的方式封装,只对外提供接口。

2.模板方法设计模式

在父类(抽象类)中定义出各个算法的框架。

通过子类(具体类)继承父类的框架,将虚方法进行重写。

3.socket.hpp

1.搭建抽象类的算法框架

// inet就是这样的一个类存储这网络的信息
//class inetinfo
//{
//    std::string _ip;//ip
//    uint16_t _port;//端口 
//    struct sockaddr_in _addr;
//};


class Socket
{
public:
        //纯虚函数 子类继承之后必须重写
        virtual void createSokcet() = 0;//创建套接字
        virtual void bindSocket(inetinfo &info) = 0;//绑定套接字
        virtual void listen() = 0;//设为监听
        virtual sockptr accepter(inetinfo &info) = 0;//接收链接
        virtual bool connecter(inetinfo &info) = 0;//客户端连接服务器

public:
        void constructListenSocket(inetinfo &info)//创建服务端的套接字
        {
            createSokcet();
            bindSocket(info);
            listen();
        }

        void construcutClintSocket(inetinfo &info)//创建客户端的套接字
        {
            createSokcet();
            connecter(info);
        }
};

2.具体类算法实现

2.1创建套接字

void createSokcet() override
{
   _listenfd = ::socket(AF_INET, SOCK_STREAM, 0);//创建出一个用来监听的fd,不提供服务
            if (_listenfd < 0)
   {
      exit(ERROR::SOCKERROR);
   }
}

2.2绑定

 void bindSocket(inetinfo &info) override
{
     sockaddr_in addr;//一个结构体类型
     bzero(&addr, sizeof(addr));//将这个结构体全部置为0
     addr.sin_addr.s_addr = inet_addr(info.Ip().c_str());//将字符串类型的ip转化为网络格式ip
     addr.sin_port = htons(info._port);//将uint16_t类型的端口号 转化为网络格式的端口
     addr.sin_family = AF_INET;// 协议族 为AF_INET ipv4的网络协议
     socklen_t len = sizeof(addr);
     int n = bind(_listenfd, (sockaddr *)&addr, len);//将创建出来的套接字与网络信息绑定
     if (n < 0)
     {
        exit(BINDERROT);
     }
}

2.3套接字设为监听

因为tcp时面向连接的所以必须先获取连接

void listenOrDie() override
{
    //将套接字的状态设为监听
     int n = listen(_listenfd, default_num);//从_listenfd中获取连接,第二参数是链接队列的长度
     if (n < 0)
     {
        exit(LISTENERROR);
     }
}

2.4接收链接

accept接口需要返回一个sockfd用来提供服务,还需要返回一个sockaddr_in标识这个链接是来自哪个ip和端口。

using sockptr = unique_ptr<Socket>;
sockptr accepter(inetinfo &info)
{
    sockaddr_in addr;
    bzero(&addr, sizeof(addr));
    socklen_t len = sizeof(addr);
    int sockfd = accept(_listenfd, (sockaddr *)&addr, &len);
    if (sockfd < 0)
    {
      Log(Info, "accept error");
      return nullptr;
    }
    info = addr;
    return std::make_unique<Socket>(sockfd); // 返回一个基类的指针 上层就可以多态调用
}

2.5客户端连接服务器

connecter返回直接设置bool类型即可,不需要返回sockptr,因为客户端创建出的socket直接可以用来连接和业务的io。

参数info需要与那个ip和端口进行连接。

bool connecter(inetinfo &info)
{
   sockaddr_in addr;
   bzero(&addr, sizeof(addr));
   socklen_t len = sizeof(addr);
   addr.sin_addr.s_addr = inet_addr(info.Ip().c_str());
   addr.sin_family = AF_INET;
   addr.sin_port = htons(info._port);
   int n = connect(_listenfd, (sockaddr *)&addr, len);
   if (n < 0)
   {
       cout << strerror(errno) << endl;
       return false;
   }
    return true;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值