1. Stream 类封装(接口类)
目的:对文件操作/Socket 的读写操作进行一层Stream流式封装,屏蔽他们之间的一些差异,使得它们的操作更加便捷化。
1.1 接口
1.1.1 虚析构函数
1.1.2 close()
/*** @brief 关闭*/virtual void close() = 0;
1.1.3 读系列函数
1.1.3.1 虚接口
/*** @brief 读取数据* @param[out] buffer 存放数据的缓冲区* @param[in] len 期望读取数据长度* @return* @retval >0 实际读取的字节数* @retval 0 对端关闭* @retval <0 错误*/virtual int read(void *buffer, size_t len) = 0;/*** @brief 接收到数据后写入ByteArray中* @param[in] ba 接收数据的ByteArray* @param[in] len 接收数据长度* @return* @retval >0 实际读取的字节数* @retval 0 对端关闭* @retval <0 错误*/virtual int read(ByteArray::ptr ba, size_t len) = 0;
1.1.3.2 readFixSize()
功能:读取数据,读够指定字节才会返回
/*** @brief 读取数据,读够指定字节才会返回* @param[out] buffer 存放数据的缓冲区* @param[in] len 期望读取数据长度* @return* @retval >0 实际读取的字节数* @retval 0 对端关闭* @retval <0 错误*/virtual int readFixSize(void *buffer, size_t len);int Stream::readFixSize(void *buffer, size_t len){//剩余应读字节数size_t left = len;//缓冲区偏移量size_t offset = 0;while(left > 0){size_t ret = read((char*)buffer + offset, left);if(ret <= 0){return ret;}offset += ret;left -= ret;}//返回出已经读完的字节数return len;}
1.1.3.3 (重载)readFixSize()
功能:接收到数据后写入ByteArray中,读够指定字节才会返回
/*** @brief 接收到数据后写入ByteArray中,读够指定字节才会返回* @param[in] ba 接收数据的ByteArray* @param[in] len 接收数据长度* @return* @retval >0 实际读取的字节数* @retval 0 对端关闭* @retval <0 错误*/virtual int readFixSize(ByteArray::ptr ba, size_t len);int Stream::readFixSize(ByteArray::ptr ba, size_t len){//剩余应读字节数size_t left = len;while(left > 0){//复用read()函数size_t ret = read(ba, left);if(ret <= 0){return ret;}left -= ret;}//返回出已经读完的字节数return len;}
1.1.4 写系列函数
1.1.4.1 虚接口
/*** @brief 写入数据* @param[in] buffer 存放数据的缓冲区* @param[in] len 期望写入数据长度* @return* @retval >0 实际写入的字节数* @retval <0 错误*/virtual int write(const void* buffer, size_t len) = 0;/*** @brief 拿出ByteArray中数据写入* @param[out] ba 拿出数据的ByteArray* @param[in] len 期望写入数据长度* @return* @retval >0 实际读取的字节数* @retval <0 错误*/virtual int write(ByteArray::ptr ba, size_t len) = 0;
1.1.4.2 writeFixSize()
功能:写入数据,写入指定字节才会返回
/*** @brief 写入数据,写入指定字节才会返回* @param[in] buffer 存放数据的缓冲区* @param[in] len 期望写入数据长度* @return* @retval >0 实际读取的字节数* @retval <0 错误*/virtual int writeFixSize(const void* buffer, size_t len);int Stream::writeFixSize(const void* buffer, size_t len){//剩余应写入字节数size_t left = len;//缓冲区偏移量size_t offset = 0;while(left > 0){size_t ret = write((char*)buffer + offset, left);if(ret <= 0){return ret;}offset += ret;left -= ret;}//返回出已经写完的字节数return len;}
1.1.4.3 (重载)writeFixSize()
功能:拿出ByteArray中数据写入,写入指定字节才会返回
/*** @brief 拿出ByteArray中数据写入,写入指定字节才会返回* @param[out] ba 拿出数据的ByteArray* @param[in] len 期望写入数据长度* @return* @retval >0 实际读取的字节数* @retval <0 错误*/virtual int writeFixSize(ByteArray::ptr ba, size_t len);int Stream::writeFixSize(ByteArray::ptr ba, size_t len){//剩余应写入字节数size_t left = len;while(left > 0){size_t ret = write(ba, left);if(ret <= 0) //出错就要返回{return ret;}left -= ret;}//返回出已经写完的字节数return len;}
2. Socket Stream类封装
目的:封装一套和业务联系紧密的socket接口。和之前socket.h/socket.cpp封装C API不同,之前为了避免裸用关于socket的接口
· 类关系

2.1 成员变量
class SOcketStream{........protected://Socket对象智能指针Socket::ptr m_sock;//句柄全权管理标志位bool m_owner;};
2.2 接口
2.2.1 构造函数
/*** @brief SocketStream类构造函数* @param[in] sock 套接字对象智能指针* @param[in] owner 句柄关闭是否由本类来自动操作*/SocketStream(Socket::ptr sock, bool owner = true);SocketStream::SocketStream(Socket::ptr sock, bool owner):m_sock(sock),m_owner(owner){}
2.2.2 析构函数
/*** @brief SocketStream类析构函数 owner=true就close()*/~SocketStream();SocketStream::~SocketStream(){if(m_owner && m_sock)m_sock->close();}
2.2.3 isConnected()
功能:判断套接字是否处于连接状态
/*** @brief 套接字是否处于连接状态* @return true 处于连接* @return false 处于不连接*/bool isConnected() const;bool SocketStream::isConnected() const{return m_sock && m_sock->isConnected();}
2.2.4 重写接口
2.2.4.1 读系列函数
virtual int read(void *buffer, size_t len) override;virtual int read(ByteArray::ptr ba, size_t len) override;
1). read(void *buffer, size_t len)
virtual int read(void *buffer, size_t len) override;int SocketStream::read(void *buffer, size_t len){if(!isConnected())return -1;return m_sock->recv(buffer, len);}
2). read(ByteArray::ptr ba, size_t len)(难点)
virtual int read(ByteArray::ptr ba, size_t len) override;int SocketStream::read(ByteArray::ptr ba, size_t len){if(!isConnected())return -1;//通过iovec和ByteArray内存空间建立映射//获取到即将写入的空间std::vector<struct iovec> iovs;ba->getWriteBuf(iovs, len);//接收数据 直接就写入到了指向ByteArray的内存空间中int ret = m_sock->recv(&iovs[0], iovs.size());//由于getWriteBuf() 并不会修改内存指针位置 手动修改m_positionif(ret > 0){ba->setPosition(ba->getPosition() + ret);}return ret;}
2.2.4.2 写系列函数
virtual int write(const void* buffer, size_t len) override;virtual int write(ByteArray::ptr ba, size_t len) override;
1). write(const void* buffer, size_t len)
virtual int write(const void* buffer, size_t len) override;int SocketStream::write(const void* buffer, size_t len){if(!isConnected())return -1;return m_sock->send(buffer, len);}
2). write(ByteArray::ptr ba, size_t len)
virtual int write(ByteArray::ptr ba, size_t len) override;int SocketStream::write(ByteArray::ptr ba, size_t len){if(!isConnected())return -1;std::vector<struct iovec> iovs;ba->getReadBuf(iovs, len);int ret = m_sock->send(&iovs[0], iovs.size());if(ret > 0){ba->setPosition(ba->getPosition() + ret);}return ret;}
2.2.4.3 close()
virtual void close() override;void SocketStream::close(){if(m_sock && isConnected())m_sock->close();}
