TCP、消息分包和协议设计
TCP是一种流式协议
TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。
流式协议的特点是什么?就像流水连续不断那样,消息之间没有边界。例如send了3条消息(这里的“消息”是指应用层的一个完整的协议包),分别是100字节、50字节、80字节,recv时可能收到的是230字节,就是说一次recv收到了3条消息,需要应用逻辑自己对recv到的数据进行分析,得出完整的消息。能一次recv到多个消息,也可能一次recv到一个半消息或半个消息,都是有可能的,这就是流式协议的特点。有的文章讲的粘包也是这个概念。
消息分包
既然TCP是一种流式协议,需要应用层自己来分析出完整的消息,那有哪些方式来确定一个完整消息呢?这个就是应用层通讯协议设计的工作了。
先看看最常见的HTTP协议是如何来分包的。HTTP协议是一种文本协议(非二进制协议),用\r\n\r\n来分割消息头和消息体,HTTP请求的消息头中有Content-Length来告知消息体有多大,如果没有该字段就表示无消息体,GET请求大多是这样。HTTP响应的消息头中,或者有Content-Length,或者有Transfer-Encoding: chunked告知以chunk模式分析消息体。
HTTP请求信息由3部分组成:
1、请求方法(GET/POST)、URI、协议/版本
2、请求头(Request Header)
3、请求正文,请求正文和请求头要有空行。这个空行必须存在,说明结束请求头传输,开始传输正文请求。
HTTP请求 GET/HTTP/1.1
[请求头]
Accept:image/gif.image/jpeg,*/*
Accept-Language:zh-cn
Connection:Keep-Alive
Host:localhost
User-Agent:Mozila/4.0(compatible;MSIE5.;Window NT5.)
Accept-Encoding:gzip,deflate
[请求正文]
username=ring&password=
http响应格式
HTTP应答与HTTP请求相似,HTTP响应也由3个部分构成,分别是:
1、状态行
2、响应头(Response Header)
3、响应正文
HTTP响应1:Conetent-Length HTTP/1.1 200 OK
SERVER: name
DATE: Fri, 22 Dec 2017 10:50:38 GMT
Content-Type: image/gif
Content-Length: 43
Last-Modified: Mon, 1 Dec 2017 13:23:42 GMT
Connection: keep-alive
Expires: Fri, 22 Dec 2017 10:50:38 GMT
Cache-Control: max-age=0
Accept-Ranges: bytes GIF89a二进制数据 HTTP响应2:Transfer-Encoding
HTTP/1.1 200 OK
DATE: Fri, 22 Dec 2017 10:55:50 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Expires: Fri, 22 Dec 2017 10:55:50 GMT
Cache-Control: max-age=7200
Content-Encoding: gzip 91a
具体的数据
0
HTTP用\r\n\r\n来分割消息头和消息体,这种用特定字符/字符串来分割或分包的方式,还有不少协议用到。例如FTP/SMTP/POP3都是用\n来作为一个命令结束的标志。这种消息分包的方式,需要应用层去扫描已recv到的数据,性能上还不够高效,代码不严谨的还容易被攻击。在需要自定义协议的项目中,不少选择用二进制协议,解析高效,安全性更好些。
最简单的二进制协议分包方式是消息的头4个字节表示消息的总长度。这种方式还需要对最大消息长度做个限制,例如64K或1024K大小,避免超大数据包对接收方缓冲区的破坏。更进一步的,可以加入简单校验方法。例如消息头1个字节固定式0x2,消息的最后1个字节固定式0x3,消息总长度放在第2~5字节。这样收到完整消息后,如果头尾不是0x2和0x3,就直接异常处理。
协议设计
消息分包是协议设计的一个工作,协议设计的话题还不少,这里以HTTP协议为例,简要的说说里面设计的点,自己设计的协议也可以对照着有选择的使用,原理是共通的。
由消息头+消息体组成:空行分割HTTP head和body,HTTP头的每一行以\r\n结尾,空行就是\r\n\r\n
消息分包:如上所述,HTTP用Content-Length和Transfer-Encodeing来分包
消息压缩:请求中有Accept-Encoding字段,响应中用Content-Encoding字段表明压缩方式,一般采用gzip压缩
消息加密:https (SSL: Secure Socket Layer)
消息ID:URL就是消息ID
响应的状态码:第一个数字定义了响应的类别。
1xx:指示信息--表示请求已接收,继续处理
2xx:成功--表示请求已被成功接收、理解、接受
3xx:重定向--要完成请求必须进行更进一步的操作
4xx:客户端错误--请求有语法错误或请求无法实现
5xx:服务器端错误--服务器未能实现合法的请求
协议版本号: HTTP/1.1中的1.1就是HTTP 1.1版本
长连接:请求中Connection: keep-alive表示希望服务器保持连接,减少TCP连接的开销
字符集: Content-Type字段表明了字符集,例如: Content-Type: text/html; charset=gb2312
字符转义:URL中的参数需要做URL转义处理,例如http://xx.com/do?name=t%2F%3F%23%3Daa表示name为t/?#=aa
在我们自己设计协议时,可以有选择的使用,如果消息比较大,可以采用支持压缩;如果要兼容多个版本的协议,那版本号必不可少。如果采用二进制协议,字符集和字符穿衣的用处不大。
TCP、消息分包和协议设计的更多相关文章
- 主程的晋升攻略(4):TCP、消息分包和协议设计
在<主程的晋升攻略(3):IP.DNS和CDN>中,一次网络请求经过DNS解析知道了目的IP,如今就要发出网络包,这里我们说一说TCP的相关话题. TCP是一种流式协议 讲网络编程的教科书 ...
- Fixed-Length Frames 谈谈网络编程中应用层(基于TCP/UDP)的协议设计
http://blog.sina.com.cn/s/blog_48d4cf2d0101859x.html 谈谈网络编程中应用层(基于TCP/UDP)的协议设计 (2013-04-27 19:11:00 ...
- TCP协议设计原理
TCP协议设计原理 最近去了解TCP协议,发现这是一个特别值得深思的协议.在本篇博客中,不会长篇大论的给大家介绍TCP协议特点.包头格式以及TCP的连接和断开等基本原理,而是会带大家深入理解为什么要这 ...
- Mina、Netty、Twisted一起学(二):TCP消息边界问题及按行分割消息
在TCP连接开始到结束连接,之间可能会多次传输数据,也就是服务器和客户端之间可能会在连接过程中互相传输多条消息.理想状况是一方每发送一条消息,另一方就立即接收到一条,也就是一次write对应一次rea ...
- 分布式发布订阅消息系统 Kafka 架构设计[转]
分布式发布订阅消息系统 Kafka 架构设计 转自:http://www.oschina.net/translate/kafka-design 我们为什么要搭建该系统 Kafka是一个消息系统,原本开 ...
- 2018-2019-1-20165221&20165225 《信息安全系统设计》实验五:通讯协议设计
2018-2019-1-20165221&20165225 <信息安全系统设计>-实验五:通讯协议设计 OpenSSL学习: 简介: OpenSSL是为网络通信提供安全及数据完整性 ...
- python 全栈开发,Day33(tcp协议和udp协议,互联网协议与osi模型,socket概念,套接字(socket)初使用)
先来回顾一下昨天的内容 网络编程开发架构 B/S C/S架构网卡 mac地址网段 ip地址 : 表示了一台电脑在网络中的位置 子网掩码 : ip和子网掩码按位与得到网段 网关ip : 内置在路由器中的 ...
- im协议设计选型【转】
一.im协议的分层设计所谓“协议”是双方共同遵守的规则,例如:离婚协议,停战协议.协议有语法.语义.时序三要素.(1)语法:即数据与控制信息的结构或格式(2)语义:即需要发出何种控制信息,完成何种动作 ...
- 网络编程基础socket 重要中:TCP/UDP/七层协议
计算机网络的发展及基础网络概念 问题:网络到底是什么?计算机之间是如何通信的? 早期 : 联机 以太网 : 局域网与交换机 广播 主机之间“一对所有”的通讯模式,网络对其中每一台主机发出的信号都进行无 ...
随机推荐
- Hadoop记录-fair公平调度队列管理
<?xml version="1.0"?> <allocations> <queue name="root"> <qu ...
- [NIO-4]选择器
选择器 最后,我们探索一下选择器.由于选择器内容比较多,所以本篇先偏理论地讲一下,后一篇讲代码,文章也没有什么概括.总结的,写到哪儿算哪儿了,只求能将选择器写明白,并且将一些相对重要的内容加粗标红. ...
- C语言数据类型的转换(隐式转换)
算术运算符中的转换规则: double ←── float 高↑long↑unsigned↑int ←── char,short 低 注意: 图中横向箭头表示必须的转换,如两个float型数参加运算, ...
- golang channle阻塞
当一个channle容量写满时,会出现阻塞状态 package main func main() { var c1 = make(chan int, 10) for i := 0; i < 10 ...
- JavaScript深度克隆(递归)
今天在深度理解JQuery源码时,剖析extend时: jQuery.extend = jQuery.fn.extend = function() { //... } 感觉该方法的一部分功能与深度克隆 ...
- windows server 禁用智能卡服务的步骤
许多用户对于系统中的很多功能都不太了解,其中智能卡服务更是少有人知.智能卡服务就是对插入的智能卡进行管理和访问控制,大多数用户都无需使用此项功能.那么在Win7系统中要怎么取消智能卡服务呢? 1.首先 ...
- 面向对象(Object Orientation Programming)
Three characteristic of object orientation: Encapsulation: capturing data and keeping it safely and ...
- 二叉树的python可视化和常用操作代码
二叉树是一个重要的数据结构, 本文基于"二叉查找树"的python可视化 pybst 包, 做了一些改造, 可以支持更一般的"二叉树"可视化. 关于二叉树和二叉 ...
- Extjs.net Button点击下载jpg图片
<ext:Button ID=" AutoPostBack="false"> <DirectEvents> <Click OnEvent=& ...
- C#一例绘制字体不清晰的解决办法
public static Bitmap GetPieWithText(String text, Color color, Color fontColor,Font font) { ; Bitmap ...