1. Stream 类封装(接口类)

目的:对文件操作/Socket 的读写操作进行一层Stream流式封装,屏蔽他们之间的一些差异,使得它们的操作更加便捷化。

1.1 接口

1.1.1 虚析构函数

1.1.2 close()

  1. /**
  2. * @brief 关闭
  3. */
  4. virtual void close() = 0;

1.1.3 读系列函数

1.1.3.1 虚接口

  1. /**
  2. * @brief 读取数据
  3. * @param[out] buffer 存放数据的缓冲区
  4. * @param[in] len 期望读取数据长度
  5. * @return
  6. * @retval >0 实际读取的字节数
  7. * @retval 0 对端关闭
  8. * @retval <0 错误
  9. */
  10. virtual int read(void *buffer, size_t len) = 0;
  11. /**
  12. * @brief 接收到数据后写入ByteArray中
  13. * @param[in] ba 接收数据的ByteArray
  14. * @param[in] len 接收数据长度
  15. * @return
  16. * @retval >0 实际读取的字节数
  17. * @retval 0 对端关闭
  18. * @retval <0 错误
  19. */
  20. virtual int read(ByteArray::ptr ba, size_t len) = 0;

1.1.3.2 readFixSize()

功能:读取数据,读够指定字节才会返回

  1. /**
  2. * @brief 读取数据,读够指定字节才会返回
  3. * @param[out] buffer 存放数据的缓冲区
  4. * @param[in] len 期望读取数据长度
  5. * @return
  6. * @retval >0 实际读取的字节数
  7. * @retval 0 对端关闭
  8. * @retval <0 错误
  9. */
  10. virtual int readFixSize(void *buffer, size_t len);
  11. int Stream::readFixSize(void *buffer, size_t len)
  12. {
  13. //剩余应读字节数
  14. size_t left = len;
  15. //缓冲区偏移量
  16. size_t offset = 0;
  17. while(left > 0)
  18. {
  19. size_t ret = read((char*)buffer + offset, left);
  20. if(ret <= 0)
  21. {
  22. return ret;
  23. }
  24. offset += ret;
  25. left -= ret;
  26. }
  27. //返回出已经读完的字节数
  28. return len;
  29. }

1.1.3.3 (重载)readFixSize()

功能:接收到数据后写入ByteArray中,读够指定字节才会返回

  1. /**
  2. * @brief 接收到数据后写入ByteArray中,读够指定字节才会返回
  3. * @param[in] ba 接收数据的ByteArray
  4. * @param[in] len 接收数据长度
  5. * @return
  6. * @retval >0 实际读取的字节数
  7. * @retval 0 对端关闭
  8. * @retval <0 错误
  9. */
  10. virtual int readFixSize(ByteArray::ptr ba, size_t len);
  11. int Stream::readFixSize(ByteArray::ptr ba, size_t len)
  12. {
  13. //剩余应读字节数
  14. size_t left = len;
  15. while(left > 0)
  16. {
  17. //复用read()函数
  18. size_t ret = read(ba, left);
  19. if(ret <= 0)
  20. {
  21. return ret;
  22. }
  23. left -= ret;
  24. }
  25. //返回出已经读完的字节数
  26. return len;
  27. }

1.1.4 写系列函数

1.1.4.1 虚接口

  1. /**
  2. * @brief 写入数据
  3. * @param[in] buffer 存放数据的缓冲区
  4. * @param[in] len 期望写入数据长度
  5. * @return
  6. * @retval >0 实际写入的字节数
  7. * @retval <0 错误
  8. */
  9. virtual int write(const void* buffer, size_t len) = 0;
  10. /**
  11. * @brief 拿出ByteArray中数据写入
  12. * @param[out] ba 拿出数据的ByteArray
  13. * @param[in] len 期望写入数据长度
  14. * @return
  15. * @retval >0 实际读取的字节数
  16. * @retval <0 错误
  17. */
  18. virtual int write(ByteArray::ptr ba, size_t len) = 0;

1.1.4.2 writeFixSize()

功能:写入数据,写入指定字节才会返回

  1. /**
  2. * @brief 写入数据,写入指定字节才会返回
  3. * @param[in] buffer 存放数据的缓冲区
  4. * @param[in] len 期望写入数据长度
  5. * @return
  6. * @retval >0 实际读取的字节数
  7. * @retval <0 错误
  8. */
  9. virtual int writeFixSize(const void* buffer, size_t len);
  10. int Stream::writeFixSize(const void* buffer, size_t len)
  11. {
  12. //剩余应写入字节数
  13. size_t left = len;
  14. //缓冲区偏移量
  15. size_t offset = 0;
  16. while(left > 0)
  17. {
  18. size_t ret = write((char*)buffer + offset, left);
  19. if(ret <= 0)
  20. {
  21. return ret;
  22. }
  23. offset += ret;
  24. left -= ret;
  25. }
  26. //返回出已经写完的字节数
  27. return len;
  28. }

1.1.4.3 (重载)writeFixSize()

功能:拿出ByteArray中数据写入,写入指定字节才会返回

  1. /**
  2. * @brief 拿出ByteArray中数据写入,写入指定字节才会返回
  3. * @param[out] ba 拿出数据的ByteArray
  4. * @param[in] len 期望写入数据长度
  5. * @return
  6. * @retval >0 实际读取的字节数
  7. * @retval <0 错误
  8. */
  9. virtual int writeFixSize(ByteArray::ptr ba, size_t len);
  10. int Stream::writeFixSize(ByteArray::ptr ba, size_t len)
  11. {
  12. //剩余应写入字节数
  13. size_t left = len;
  14. while(left > 0)
  15. {
  16. size_t ret = write(ba, left);
  17. if(ret <= 0) //出错就要返回
  18. {
  19. return ret;
  20. }
  21. left -= ret;
  22. }
  23. //返回出已经写完的字节数
  24. return len;
  25. }

2. Socket Stream类封装

目的:封装一套和业务联系紧密的socket接口。和之前socket.h/socket.cpp封装C API不同,之前为了避免裸用关于socket的接口

· 类关系

Stream 开发 - 图1

2.1 成员变量

  1. class SOcketStream
  2. {
  3. ....
  4. ....
  5. protected:
  6. //Socket对象智能指针
  7. Socket::ptr m_sock;
  8. //句柄全权管理标志位
  9. bool m_owner;
  10. };

2.2 接口

2.2.1 构造函数

  1. /**
  2. * @brief SocketStream类构造函数
  3. * @param[in] sock 套接字对象智能指针
  4. * @param[in] owner 句柄关闭是否由本类来自动操作
  5. */
  6. SocketStream(Socket::ptr sock, bool owner = true);
  7. SocketStream::SocketStream(Socket::ptr sock, bool owner)
  8. :m_sock(sock)
  9. ,m_owner(owner)
  10. {
  11. }

2.2.2 析构函数

  1. /**
  2. * @brief SocketStream类析构函数 owner=true就close()
  3. */
  4. ~SocketStream();
  5. SocketStream::~SocketStream()
  6. {
  7. if(m_owner && m_sock)
  8. m_sock->close();
  9. }

2.2.3 isConnected()

功能:判断套接字是否处于连接状态

  1. /**
  2. * @brief 套接字是否处于连接状态
  3. * @return true 处于连接
  4. * @return false 处于不连接
  5. */
  6. bool isConnected() const;
  7. bool SocketStream::isConnected() const
  8. {
  9. return m_sock && m_sock->isConnected();
  10. }

2.2.4 重写接口

2.2.4.1 读系列函数

  1. virtual int read(void *buffer, size_t len) override;
  2. virtual int read(ByteArray::ptr ba, size_t len) override;

1). read(void *buffer, size_t len)
  1. virtual int read(void *buffer, size_t len) override;
  2. int SocketStream::read(void *buffer, size_t len)
  3. {
  4. if(!isConnected())
  5. return -1;
  6. return m_sock->recv(buffer, len);
  7. }

2). read(ByteArray::ptr ba, size_t len)(难点)
  1. virtual int read(ByteArray::ptr ba, size_t len) override;
  2. int SocketStream::read(ByteArray::ptr ba, size_t len)
  3. {
  4. if(!isConnected())
  5. return -1;
  6. //通过iovec和ByteArray内存空间建立映射
  7. //获取到即将写入的空间
  8. std::vector<struct iovec> iovs;
  9. ba->getWriteBuf(iovs, len);
  10. //接收数据 直接就写入到了指向ByteArray的内存空间中
  11. int ret = m_sock->recv(&iovs[0], iovs.size());
  12. //由于getWriteBuf() 并不会修改内存指针位置 手动修改m_position
  13. if(ret > 0)
  14. {
  15. ba->setPosition(ba->getPosition() + ret);
  16. }
  17. return ret;
  18. }

2.2.4.2 写系列函数

  1. virtual int write(const void* buffer, size_t len) override;
  2. virtual int write(ByteArray::ptr ba, size_t len) override;

1). write(const void* buffer, size_t len)
  1. virtual int write(const void* buffer, size_t len) override;
  2. int SocketStream::write(const void* buffer, size_t len)
  3. {
  4. if(!isConnected())
  5. return -1;
  6. return m_sock->send(buffer, len);
  7. }

2). write(ByteArray::ptr ba, size_t len)
  1. virtual int write(ByteArray::ptr ba, size_t len) override;
  2. int SocketStream::write(ByteArray::ptr ba, size_t len)
  3. {
  4. if(!isConnected())
  5. return -1;
  6. std::vector<struct iovec> iovs;
  7. ba->getReadBuf(iovs, len);
  8. int ret = m_sock->send(&iovs[0], iovs.size());
  9. if(ret > 0)
  10. {
  11. ba->setPosition(ba->getPosition() + ret);
  12. }
  13. return ret;
  14. }

2.2.4.3 close()

  1. virtual void close() override;
  2. void SocketStream::close()
  3. {
  4. if(m_sock && isConnected())
  5. m_sock->close();
  6. }

3. FileStream类封装