2021SC@SDUSC
目录
一.前置知识点
1.memcpy函数
2.C++ vector容器
3.ntohl()、htonl()函数
二.具体代码分析
本篇接上一篇(62条消息) 搜狗workflow——C++并行计算与异步网络引擎 序列化与反序列化 代码分析(五)_wadaxinoli的博客-CSDN博客
上一篇中,我们分析了message.cc中的头文件,了解到了一些库的内容和用法。那么这一篇我们将介绍message.cc的具体的一部分代码分析。
按照惯例,我们先介绍代码中的知识点啦!
一.前置知识点
1.memcpy函数
memcpy函数是C标准库-stdlib.h中的函数。该函数的声明是:
void *memcpy(void *str1, const void *str2, size_t n)
其中
str1 -- 指向用于存储复制内容的目标数组;
str2 -- 指向要复制的数据源,类型强制转换为 void* 指针;
n -- 要被复制的字节数。
简单来说memcpy函数就是把str2中的n个字节复制给str1。
2.C++ vector容器
vector(向量)是一个封装了动态大小数组的顺序容器,它能存放任意类型的动态数组。顺序容器中的元素按照严格的线性顺序排序。可以通过元素在序列中的位置访问对应的元素。
动态数组的属性决定了vector支持对序列中的任意元素进行快速直接访问,甚至可以通过指针算述进行该操作。提供了在序列末尾相对快速地添加/删除元素的操作。
3.ntohl()、htonl()函数
ntohl()指的是ntohl函数,是将一个无符号长整形数从网络字节顺序转换为主机字节顺序, ntohl()返回一个以主机字节顺序表达的数。
htonl()将主机数转换成无符号长整型的网络字节顺序。本函数将一个32位数从主机字节顺序转换成网络字节顺序。
二.具体代码分析
介绍完知识点,我们就正式进入代码分析啦!
namespace protocol
{
int TutorialMessage::encode(struct iovec vectors[], int max)
//iovec结构体定义了一个vector顺序容器。
{
uint32_t n = htonl(this->body_size);
//将主机数转换成无符号长整型的网络字节顺序。
memcpy(this->head, &n, 4);
//this->head的值为&n的四个字节。
vectors[0].iov_base = this->head;
//iov_base 作为一个指针,用于记录 buffer 地址
vectors[0].iov_len = 4;
//iov_len 表示 buffer 的大小。
vectors[1].iov_base = this->body;
vectors[1].iov_len = this->body_size;
return 2;
}
//下面是TutorialMessage的实现
int TutorialMessage::append(const void *buf, size_t size)
{
if (this->head_received < 4)
{
size_t head_left;
void *p;
p = &this->head[head_received];
head_left = 4 - this->head_received;
if (size < 4 - this->head_received)
{
memcpy(p, buf, size);
this->head_received += size;
return 0;
}
//在head_received < 4的前提下,如果size小于 4 - this->head_received,head_received就加上size。
memcpy(p, buf, head_left);
size -= head_left;
buf = (const char *)buf + head_left;
p = this->head;
this->body_size = ntohl(*(uint32_t *)p);
// 将一个无符号长整形数从网络z字节顺序转换为主机字节顺序。
if (this->body_size > this->size_limit)
{
errno = EMSGSIZE;
return -1;
}
//errno.h中的一个宏。
this->body = (char *)malloc(this->body_size);
if (!this->body)
return -1;
this->body_received = 0;
}
size_t body_left = this->body_size - this->body_received;
if (size > body_left)
{
errno = EBADMSG;
return -1;
}
//errno.h中的一个宏。
memcpy(this->body, buf, size);
if (size < body_left)
return 0;
return 1;
}
//size小于body_left时直接返回0.



