Socket流接口模块概述
基于序列化模块封装了读和写操作,但是socket
的API
并不保证一定能够写或读到规定的字节数,所以封装了readFixSize
、writeFixSize
保证一定操作规定字节的数据。
该模块主要有以下几类:
- class Stream:基类,抽象类。
- class SocketStream:内部封装一个
socket
。
详解
class Stream
该类为抽象类,提供5个纯虚函数
// 读操作,保存到buffer中
virtual int read(void* buffer, size_t length) = 0;
// 读操作,保存到ByteArray中
virtual int read(ByteArray::ptr ba, size_t length) = 0;
// 写操作,从buffer中写
virtual int write(const void* buffer, size_t length) = 0;
// 写操作,从ByteArray中写
virtual int write(ByteArray::ptr ba, size_t length) = 0;
// 关闭流
virtual void close() = 0;
readFixSize(读固定长度的数据,读取到内存)
int Stream::readFixSize(void* buffer, size_t length){
// 偏移量
size_t offset = 0;
// 剩余字节数
size_t left = length;
// 若没读完
while (left > 0) {
// 读数据
size_t len = read((char*)buffer + offset, left);
// 读取失败
if (len <= 0) {
return len;
}
// 更新偏移量
offset += len;
// 更新剩余字节数
left -= len;
}
return length;
}
readFixSize(读固定长度的数据,读取到ByteArray)
int Stream::readFixSize(ByteArray::ptr ba, size_t length) {
size_t left = length;
while (left > 0) {
size_t len = read(ba, left);
if (len <= 0) {
return len;
}
left -= len;
}
return length;
}
writeFixSize(写固定长度的数据,从内存写)
int Stream::writeFixSize(const void* buffer, size_t length) {
size_t offset = 0;
size_t left = length;
while (left > 0) {
size_t len = write((const char*)buffer + offset, left);
if (len <= 0) {
return len;
}
offset += len;
left -= len;
}
return length;
}
writeFixSize(写固定长度的数据,从ByteArray写)
int Stream::writeFixSize(ByteArray::ptr ba, size_t length) {
size_t left = length;
while (left > 0) {
size_t len = write(ba, left);
if (len <= 0) {
return len;
}
left -= len;
}
return length;
}
class SocketStream
mumber(成员变量)
// socekt
Socket::ptr m_socket;
// 是否自己控制socket
bool m_owner;
SocketStream(构造函数)
SocketStream::SocketStream(Socket::ptr sock, bool owner)
:m_socket(sock)
,m_owner(owner) {
}
~SocketStream(析构函数)
若自己控制则关闭socket
。
SocketStream::~SocketStream() {
if (m_owner && m_socket) {
m_socket->close();
}
}
isConnected(连接状态)
bool SocketStream::isConnected() const {
return m_socket && m_socket->isConnected();
}
close(关闭socket)
void SocketStream::close() {
if (m_socket) {
m_socket->close();
}
}
read(读数据,读取到内存)
int SocketStream::read(void* buffer, size_t length) {
if (!isConnected()) {
return -1;
}
return m_socket->recv(buffer, length);
}
read(读数据,读取到ByteArray)
int SocketStream::read(ByteArray::ptr ba, size_t length) {
if (!isConnected()) {
return -1;
}
std::vector<iovec> iovs;
// 获取可写内存,将数据写到ByteArray中
ba->getWriteBuffers(iovs, length);
// 读取数据,放到第一个元素中
int rt = m_socket->recv(&iovs[0], iovs.size());
if (rt > 0) {
// 写入成功,设置position
ba->setPosition(ba->getPosition() + rt);
}
return rt;
}
write(写数据,从内存写)
int SocketStream::write(const void* buffer, size_t length) {
if (!isConnected()) {
return -1;
}
return m_socket->send(buffer, length);
}
write(写数据,从ByteArray写)
int SocketStream::write(ByteArray::ptr ba, size_t length) {
if (!isConnected()) {
return -1;
}
std::vector<iovec> iovs;
// 获取可读内存,从ByteArray读数据
ba->getReadBuffers(iovs, length);
// 发送数据,将第一个元素iovec发送
int rt = m_socket->send(&iovs[0], iovs.size());
if (rt > 0) {
// 发送成功,设置position
ba->setPosition(ba->getPosition() + rt);
}
return rt;
}