当前位置: 首页 > article >正文

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;
}


http://www.kler.cn/a/288488.html

相关文章:

  • 高效稳定!新加坡服务器托管方案助力企业全球化布局
  • SQL面试题——奔驰SQL面试题 车辆在不同驾驶模式下的时间
  • 微服务(二)
  • C++面试基础知识:排序算法 C++实现
  • 4.4 软件设计:UML顺序图
  • Qt 实现文件监控程序
  • Java GC机制:Minor GC与Full GC的触发条件
  • 假期作业--数据结构
  • uniapp插槽用法
  • vue子组件样式影响父组件
  • 每天一个数据分析题(五百一十六)- 贝叶斯分类算法
  • Axure打造科技感数据可视化大屏原型
  • 网络安全宗旨和目标
  • OpenCV颜色空间转换(1)颜色空间转换函数cvtColor()的使用
  • 【论文阅读】skill code 和 one-shot manipulate
  • C++ 设计模式——职责链模式
  • Go父类调用子类方法(虚函数调用)
  • stm32之I2C通信外设
  • 提升RAG检索回答质量: Shortwave的 4 大优化指南
  • 使用 Milvus Lite、Llama3 和 LlamaIndex 搭建 RAG 应用
  • 住宅IP与机房IP:哪种更适合业务应用?
  • 51单片机-第十节-独立按键及数码管优化
  • shell脚本—————局域网IP扫描
  • 开放式耳机漏音有多大?五大超值爆款推荐!
  • 【数据可视化技术】使用Matplotlib、Seaborn进行数据可视化
  • 9、Django Admin优化查询