muduo编程示例2019-11-02
//discard 长连接应用层协议,关注:消息/数据到达事件。
void DiscardServer::onMessage(const TcpConnectionPtr& conn,
Buffer* buf,
Timestamp time)
{
string msg(buf->retrieveAllAsString());
LOG_INFO << conn->name() << " discards " << msg.size()
<< " bytes received at " << time.toString();
}
daytime 短连接协议,发送完后,服务器主动断开。关注连接已建立事件。
void DiscardServer::onConnection(const TcpConnectionPtr& conn)
{
LOG_INFO << "DiscardServer - " << conn->peerAddress().toIpPort() << " -> "
<< conn->localAddress().toIpPort() << " is "
<< (conn->connected() ? "UP" : "DOWN");
}
time 返回一个32-bit的整数。表示从1970-01-01 00:00:00Z到现在的秒数。关注连接已建立事件。
void TimeServer::onConnection(const muduo::net::TcpConnectionPtr& conn)
{
LOG_INFO << "TimeServer - " << conn->peerAddress().toIpPort() << " -> "
<< conn->localAddress().toIpPort() << " is "
<< (conn->connected() ? "UP" : "DOWN");
if (conn->connected())
{
time_t now = ::time(NULL);
int32_t be32 = sockets::hostToNetwork32(static_cast<int32_t>(now));
conn->send(&be32, sizeof be32);
conn->shutdown();
}
}
chargen协议只发送数据,不接收数据。关注消息/数据发送完毕事件。
void ChargenServer::onConnection(const TcpConnectionPtr& conn)
{
LOG_INFO << "ChargenServer - " << conn->peerAddress().toIpPort() << " -> "
<< conn->localAddress().toIpPort() << " is "
<< (conn->connected() ? "UP" : "DOWN");
if (conn->connected())
{
conn->setTcpNoDelay(true);
conn->send(message_);
}
}
void ChargenServer::onMessage(const TcpConnectionPtr& conn,
Buffer* buf,
Timestamp time)
{
string msg(buf->retrieveAllAsString());
LOG_INFO << conn->name() << " discards " << msg.size()
<< " bytes received at " << time.toString();
}
void ChargenServer::onWriteComplete(const TcpConnectionPtr& conn)
{
transferred_ += message_.size();
conn->send(message_);
}
muduo把主动关闭连接这件事分为两步,如果主动关闭连接,它会先关闭写端,等对方关闭之后,再关本地的读端。
Tcpconnection对象析构的时候,正式关闭。
可以从/proc/pid/fd中查找没有关闭的文件描述符。
Buffer
设计目标:开发公司内部分布式程序。
网络编程使用Protobuf需要解决两个问题:长度,类型。
长度:Protobuf打包数据没有自带长度信息或终结符,需要有应用程序自己在发生和接受的时候做正确的切分。
类型:Protobuf打包的数据没有自带类型信息,需要由发送方把类型信息传给接收方,接收方创建具体的Protobuf Message对象,再做反序列化。
长度:通常在每个消息前面加固定长度的length header.
类型:Protobuf对此有内建的支持。
一种做法是:Protobuf data之前加上header,header中包含消息长度和类型信息。
类型信息的“山寨”做法主要两种:
1、在header中放int typeId,接收方用switch-case来选择对于的消息类型和处理函数;
2、在header中放string typeName,接收方用look-up table来选择对应的消息类型和处理函数。