2021SC@SDUSC
目录
一.关于序列化和反序列化
1.含义
二.序列化和反序列化的关键代码展示
1.message.h
2.message.cc
3.server.cc
4.client.cc
docs/tutorial-10-user_defined_protocol.md · 搜狗开源/workflow - Gitee.com
本篇是代码分析的最后一篇,在这里做一个关于序列化与反序列化的总结。
一.关于序列化和反序列化
1.含义
对象的序列化(Serialization),即把一个对象以流的方式,写入到文件中保存,叫写对象,也叫对象序列化,对象中包含的不仅仅是字符,使用字节流。
对象的反序列化(deserailization),即把文件中保存的对象,以流的方式读取出来,叫做读取对象,也叫对象的反序列。读取的文件保存的都是字节,使用字节流。
对象序列化的作用:在传递,和保存对象(object)的时候,保证对象的完整性和可传递性。
首先我们定义了一个序列化和反序列化的接口,在ProtocolMessage.h里;在接口中定义了两个函数,分别是encode函数:序列化函数,append函数:反序列化函数。
部分代码示例如下:
class ProtocolMessage : public CommMessageOut, public, CommMessageIn
{
private:
virtual int encode(struct iovec vectors[], int max) = 0;//encode函数为序列化函数
virtual int append(const char *buf, size_t size) = 0;//append函数为反序列化函数
……
2.优点
①将对象转为字节流存储到硬盘上,当JVM停机的话,字节流还会在硬盘上默默等待,等待下一次JVM的启动,把序列化的对象,通过反序列化为原来的对象,并且序列化的二进制序列能够减少存储空间(永久性保存对象)。
②序列化成字节流形式的对象可以进行网络传输(二进制形式),方便了网络传输。
③通过序列化可以在进程间传递对象。
二.序列化和反序列化的关键代码展示
1.message.h
在message.h中,定义了具体的方法。
class TutorialMessage : public ProtocolMessage
{
private:
virtual int encode(struct iovec vectors[], int max);
virtual int append(const void *buf, size_t size);
public:
int set_message_body(const void *body, size_t size);
void get_message_body_nocopy(void **body, size_t *size)
{
*body = this->body;
*size = this->body_size;
}
2.message.cc
在message.cc中实现了encode,append方法。
int TutorialMessage::encode(struct iovec vectors[], int max/*max==8192*/)
{
uint32_t n = htonl(this->body_size);
memcpy(this->head, &n, 4);
vectors[0].iov_base = this->head;
vectors[0].iov_len = 4;
vectors[1].iov_base = this->body;
vectors[1].iov_len = this->body_size;
return 2; /* return the number of vectors used, no more then max. */
}
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;
}
3.server.cc
在server.cc中实现了交互的过程方法。
void process(WFTutorialTask *task)
{
TutorialRequest *req = task->get_req();
TutorialResponse *resp = task->get_resp();
void *body;
size_t size;
size_t i;
req->get_message_body_nocopy(&body, &size);
for (i = 0; i < size; i++)
((char *)body)[i] = toupper(((char *)body)[i]);
resp->set_message_body(body, size);
}
4.client.cc
在client.cc方法中用锁实现与客户端交互:
WFTutorialTask *task = MyFactory::create_tutorial_task(host, port, 0, callback);
task->get_resp()->set_size_limit(4 * 1024);
Workflow::start_series_work(task, [&mutex, &cond, &finished](const SeriesWork *)
{
mutex.lock();
finished = true;
cond.notify_one();
mutex.unlock();
}
----------------------------------------------------------------------------------------------------------------------
代码来源: