本文是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<void (const muduo::net::TcpConnectionPtr&,const muduo::string& message,muduo::Timestamp)> 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<const int32_t*>(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: TcpConnectionPtrvoid send(muduo::net::TcpConnection* conn,const muduo::StringPiece& message){muduo::net::Buffer buf;buf.append(message.data(), message.size());//打包报文int32_t len = static_cast<int32_t>(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