Update tutorial-10-user_defined_protocol.md

This commit is contained in:
liyingxin
2020-08-05 15:17:47 +08:00
committed by GitHub
parent 5ebcb06afb
commit fccfc36a22

View File

@@ -17,18 +17,23 @@
# 协议的实现
用户自定义协议,需要提供协议的协议的序列化和反序列化方法这两个方法都是ProtocolMeessage类的虚函数。
用户自定义协议需要提供协议的序列化和反序列化方法这两个方法都是ProtocolMeessage类的虚函数。
另外为了使用方便我们强烈建议用户实现消息的移动构造和移动赋值用于std::move())。
在[ProtocolMessage.h](../src/protocol/ProtocolMessage.h)里,序列化反序列化接口如下:
~~~cpp
namespace protocol
{
class ProtocolMessage : public CommMessageOut, public, CommMessageIn
class ProtocolMessage : public CommMessageOut, public CommMessageIn
{
private:
virtual int encode(struct iovec vectors[], int max) = 0;
virtual int append(const char *buf, size_t size) = 0;
virtual int encode(struct iovec vectors[], int max);
/* You have to implement one of the 'append' functions, and the first one
* with arguement 'size_t *size' is recommmended. */
virtual int append(const void *buf, size_t *size)
virtual int append(const void *buf, size_t size);
...
};
@@ -42,24 +47,25 @@ private:
* 如果是UDP协议请注意总长度不超过64k并且使用不超过1024个vectorLinux一次writev只能1024个vector
* UDP协议只能用于client无法实现UDP server。
* encode返回-1表示错误。返回-1时需要置errno。如果返回值>max将得到一个EOVERFLOW错误。错误都在callback里得到。
* 为了性能考虑vector里的iov_base指指向的内容不会被复制。所以一般指向消息类的成员。
* 为了性能考虑vector里的iov_base指指向的内容不会被复制。所以一般指向消息类的成员。
### 反序列化函数append
* append函数在每次收到一个数据块时被调用。因此每条消息可能会调用多次。
* buf和size分别是收到的数据块内容和长度。用户需要把数据内容复制走。
* 如果实现了append(const void \*buf, size_t \*size)接口,可以通过修改\*size来告诉框架本次消费了多少长度。收到的size - 消费的size = 剩余的size剩余的那部分buf会由下一次append被调起时再次收到。此功能更方便协议解析当然用户也可以全部烤走自行管理则无需修改\*size。
* 如果是UDP协议一次append一定是一个完整的数据包。
* append函数返回0表示消息还不完整传输继续。返回1表示消息结束。-1表示错误需要置errno。
* 总之append的作用就是用于告诉框架消息是否已经传输结束。不要在append里做复杂的非必要的协议解析。
### errno的设置
* encode或append返回-1或其它负数都会被理解为失败需要通过errno来传递错误原因。用户会在callback里得到这个错误。
* 如果是系统调用或libc等库函数失败比如malloc,libc肯定会设置好errno用户无需再设置。
* 一些消息不合法的错误是比常见的比如可以用EBADMSGEMSGSIZE分别表示消息内容错误和消息太大。
* 如果是系统调用或libc等库函数失败比如malloc,libc肯定会设置好errno用户无需再设置。
* 一些消息不合法的错误是比常见的比如可以用EBADMSGEMSGSIZE分别表示消息内容错误和消息太大。
* 用户可以选择超过系统定义errno范围的值来表示一些自定义错误。一般大于256的值是可以用的。
* 请不要使用负数errno。因为框架内部用了负数来代表SSL错误。
在我们的示例里,消息的序列化反序列化都非常的简单。
头文件[message.h](../tutorial/tutorial-10-user_defined_protocol/message.h)里,明了request和response类
头文件[message.h](../tutorial/tutorial-10-user_defined_protocol/message.h)里,明了request和response类
~~~cpp
namespace protocol
{
@@ -68,7 +74,7 @@ class TutorialMessage : public ProtocolMessage
{
private:
virtual int encode(struct iovec vectors[], int max);
virtual int append(const char *buf, size_t size);
virtual int append(const void *buf, size_t size);
...
};
@@ -104,7 +110,7 @@ int TutorialMessage::append(const void *buf, size_t size)
size_t head_left;
void *p;
p = &this->head[head_received];
p = &this->head[this->head_received];
head_left = 4 - this->head_received;
if (size < 4 - this->head_received)
{