从层次上讲，我们是基于传输层之上的，算是应用协议。所以叫自己为：

```
基于事件和语义消息流的网络应用协议
```


因为：

* 有事件
* 有元信息（语义）
* 有流（一个流，会有一个或多个帧组成）

### 1、连接地址风格

采用 url 的形式，做为客户端的连接地址（总长不超过 512 字节）：

```
sd:tcp://19.10.2.3:9812/path?u=noear&t=1234
sd:udp://19.10.2.3:9812/path?u=noear&t=1234
sd:ws://19.10.2.3:1023/path?u=noear&t=1234
sd:kcp://19.10.2.3:1023/path?u=noear&t=1234
```

协议头架构说明:

| 应用协议 | 传输协议 | 说明                       |
|------|------|--------------------------|
| sd   |      | 表示 socket.d 应用协议，代表了帧码格式，代表了指令流 |
|      | tcp  | 表示使用 tcp 传输数据            |
|      | udp  | 表示使用 udp 传输数据            |
|      | ws   | 表示使用 ws (websocket) 传输数据 |
|      | kcp  | 表示使用 kcp 传输数据（基于 udp 的增强）            |


传输协议选择建议：

* 弱网络且数据包很小。可以考虑 udp
* 如果有 web 前端开发。可以考虑 ws
* 其它随意


### 2、帧码结构

socket.d 的流是以帧为单位进行传输。大的帧还会自动分片成小帧进行传输，到达接收端后再自动聚合。

* 帧的逻辑结构

```
frame: {flag, message: {sid, event, entity: { metaString, data}}}
```

帧的数据逻辑结构：帧里有标志和消息；消息里有流标识、事件、实体；实体里有元信息字符串和数据。

* 完整的标准帧码

```
//udp only <2k
[len:int][flag:int][sid:str(<64)][\n][event:str(<512)][\n][metaString:str(<4k)][\n][data:byte(<16m)]
```

| 字段         | 类型     | 大小  | 说明                                        |
|------------|--------|-----|-------------------------------------------|
| len        | int    | 4字节 | 帧长度（包括它自己的 4字节占位）                           |
| flag       | int    | 4字节 | 标志（相当于协议指令）                                 |
| sid        | String | 64字节以内 | 流标识。`格式为： guid`                 |
| event      | String | 512字节以内 | 事件。`格式为：可见字符 string `                            |
| metaString | String | 4Kb以内 | 元信息字符串。`格式为：通用的 uri queryString ` |
| data       | byte[] | 16Mb以内 | 数据。`格式为： byte[]`                                        |
| | | | |
| \n        | char    | 2字节 | 换行符（字符串的间隔符）。`编码为：x0a`                           |

注意1：String 的字符集由实现框架通过配置决定
<br/>
注意2：当使用 udp 传输时，帧长度不能超过 1.4K

* 简化的辅助帧码（Ping, Pong, Close），取消了 message 部分

```
[len:int][flag:int]
```

### 3、指令流

| Flag         | Value | Server                               | Client                                                | 
|--------------|-------|--------------------------------------|-------------------------------------------------------|
| Unknown      | 0     | ::close()                            | ::close()                                             | 
| Connect      | 10    | /                                    | c(Connect)->s::onOpen(),s(Connack?)->c::onOpen() | 
| Connack      | 11    | ->s::onOpen(),s(Connack?)->c         | /                                                     | 
| Ping         | 20    | /                                    | c(Ping)->s(Pong)->c                                   | 
| Pong         | 21    | ->s(Pong)->c                         | /                                                     | 
| Close        | 30    | s(Close)->c                          | c(Close)->s                                           | 
| Alarm        | 31    | s(Alarm)->c                          | c(Alarm)->s                                           | 
| Message      | 40    | s(Message)->c                        | c(Message)->s                                         | 
| Request      | 41    | s(Request)->c(Reply or ReplyEnd)->s  | c(Request)->s(Reply or ReplyEnd)->c                   |  
| Subscribe    | 42    | s(Subscribe)->c(Reply...ReplyEnd)->s | c(Subscribe)->s(Reply...ReplyEnd)->c                  | 
| Reply        | 48    | ->s(Reply)->c                        | ->c(Reply)->s                                         | 
| ReplyEnd     | 49    | ->s(ReplyEnd)->c                     | ->c(ReplyEnd)->s                                      | 

```
//The reply acceptor registration in the channel is removed after the reply is completed
```
