[sylar]C++高性能服务器框架——Socket流接口模块

353 阅读2分钟

Socket流接口模块概述

基于序列化模块封装了读和写操作,但是socketAPI并不保证一定能够写或读到规定的字节数,所以封装了readFixSizewriteFixSize保证一定操作规定字节的数据。

该模块主要有以下几类:

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