muduo学习之chat(示例源码解析)----codec.h

本文是chat示例程序中编码解码的头文件,以注释代讲解。

#ifndef MUDUO_EXAMPLES_ASIO_CHAT_CODEC_H
#define MUDUO_EXAMPLES_ASIO_CHAT_CODEC_H

#include "muduo/base/Logging.h"
#include "muduo/net/Buffer.h"
#include "muduo/net/Endian.h"
#include "muduo/net/TcpConnection.h"

class LengthHeaderCodec : muduo::noncopyable
{
 public:
  typedef std::function StringMessageCallback;

  explicit LengthHeaderCodec(const StringMessageCallback& cb)
    : messageCallback_(cb)//设置回调函数
  {
  }

  void onMessage(const muduo::net::TcpConnectionPtr& conn,
                 muduo::net::Buffer* buf,
                 muduo::Timestamp receiveTime)
  {
    while (buf->readableBytes() >= kHeaderLen) // kHeaderLen == 4
    {//当接收到的报文总长度大于kHeaderLen时
      // FIXME: use Buffer::peekInt32()
      const void* data = buf->peek();//瞥一眼报文
      int32_t be32 = *static_cast(data); // 把报文头部转换为长度
      const int32_t len = muduo::net::sockets::networkToHost32(be32);//转换为本机字节序
      if (len > 65536 || len < 0)
      {
        LOG_ERROR << "Invalid length " << len;
        conn->shutdown();  // 异常,关闭连接
        break;
      }
      else if (buf->readableBytes() >= len + kHeaderLen)
      {
        buf->retrieve(kHeaderLen);//表示我已读取头部4字节
        muduo::string message(buf->peek(), len);//读取头部之后的报文长度
        messageCallback_(conn, message, receiveTime);//回调函数
        buf->retrieve(len);
      }
      else
      {
        break;
      }
    }
  }

  // FIXME: TcpConnectionPtr
  void send(muduo::net::TcpConnection* conn,
            const muduo::StringPiece& message)
  {
    muduo::net::Buffer buf;
    buf.append(message.data(), message.size());//打包报文
    int32_t len = static_cast(message.size());//获取报文长度
    int32_t be32 = muduo::net::sockets::hostToNetwork32(len);//转换网络字节序
    buf.prepend(&be32, sizeof be32);//封装头部
    conn->send(&buf);
  }

 private:
  StringMessageCallback messageCallback_;
  const static size_t kHeaderLen = sizeof(int32_t);
};

#endif  // MUDUO_EXAMPLES_ASIO_CHAT_CODEC_H

 

你可能感兴趣的:(Linux)