muduo网络库——实现Boost.Asio聊天服务器:完整代码+注释

聊天服务一个服务端进程可以同时服务多个客户端,客户端接受键盘输入,以回车为界把消息发送给服务端,服务端收到消息之后,依次发送给每个连接到它的客户端,原来发送消息的客户端进程也会收到这条消息。 消息格式每条消息有一个4字节头部,以网络序存放字节序长度。比如两条消息“hello”和“chenshuo": 打包的代码把string message打包为muduo::net...
摘要由CSDN通过智能技术生成

聊天服务

一个服务端进程可以同时服务多个客户端,客户端接受键盘输入,以回车为界把消息发送给服务端,服务端收到消息之后,依次发送给每个连接到它的客户端,原来发送消息的客户端进程也会收到这条消息。

 

消息格式

每条消息有一个4字节头部,以网络序存放字节序长度。比如两条消息“hello”和“chenshuo":

 

打包的代码

把string message打包为muduo::net::Buffer,并通过conn发送。

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<int32_t>(message.size());
    
    //网络字节序是大端存储
    int32_t be32 = muduo::net::sockets::hostToNetwork32(len);    //读取长度
    buf.prepend(&be32, sizeof(be32));                //添加长度
    conn->send(&buf);                //发送数据
} 

 

分包的代码

void onMessage(const muduo::net::TcpConnectionPtr& conn,
                muduo::net::Buffer* buf,
                muduo::Timestamp receiveTime)
{
    while(buf->readableBytes() >= kHeaderLen)    //kHeaderLen = 4
    {
        //FIXME:use Buffer::peekInt32()
        cont void* data = buf->peek();            //读取消息长度
        int32_t be32 = *static_cast<const int32_t*>(data);    //SIGBUS
        const int32_t len = muduo::net::sockets::networkToHost32(be32);
        if(len > 65536 || len < 0)
        {
            LOG_ERROR << "Invalid length " << len;
            conn->shutdown();        //FIXME: disable reading
            break;
        }
        else if(buf->readableBytes() >= len+kHeaderLen)
        {
            buf->retrieve(kHeaderLen);         //回收数据
            muduo::string message(buf->peek(), len);    //设置消息内容
            messageCallback_(conn, message, receiveTime);    //回调用户代码
            buf->retrieve(len);                //回收所有数据
        }
        else
        {
            break;
        }
    }
}

用while循环来反复读取数据,直到Buffer中的数据不够一条完整的消息。

 

 

编解码器LengthHeaderCodec

用来解决头部信息的编解码,当已连接套接字可读时,muduo的TcpConnction会读数据并存入input buffer中,然后回调用户的函数。通过LengthHeaderCodec这一层封装,让用户代码只关心“消息到达”而不是“数据到达”。

//muduo/examples/asio/chat/codec.h

#ifndef __CODEC_H__
#define __CODEC_H__
#include<muduo/base/Logging.h>
#include<muduo/net/Buffer.h>
#include<muduo/net/Endian.h>
#include<muduo/net/TcpConnection.h>

class LengthHeaderCodec:boost::noncopyable 
{
    public:
        typedef boost::func
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值