主程序员的练成:TCP、消息分包和协议设计

在《主程序员的练成:IP、DNS和CDN》中,一次网络请求经过DNS解析知道了目的IP,现在就要发出网络包,这里我们说一说TCP的相关话题。

TCP是一种流式协议

讲网络编程的教科书一般都会对TCP的可靠传输,api用法做详细说明,但对于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请求

HTTP响应1:Conetent-Length

HTTP响应2:Transfer-Encoding

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

在我们自己设计协议时,可以有选择的使用,如果消息比较大,可以采用支持压缩;如果要兼容多个版本的协议,那版本号必不可少。如果采用二进制协议,字符集和字符穿衣的用处不大。

-------- 分割线 ---------

主程序员的练成:引言

主程序员的练成:技术篇概要

主程序员的练成:IP、DNS和CDN

最后推荐下wecode程序员云笔记──为程序员而生的开源、简洁高效的云笔记软件,使用有道云做云端存储。

★ 【语法高亮】目前支持 C/C++、C#、Pascal、Java、VB.Net、XML、HTML、Python、SQL等多种方。

★ 【云端存储】除了本地笔记本外,还增加了云存储功能,目前使用有道云笔记做为云存储。

★ 【文档加密】提供了文档加密功能,确保敏感文档的安全性。

★ 【多个本地笔记本】支持多个本地笔记本,你能够新建本地笔记本、打开、压缩和备份本地笔记本。

★ 【文章附件】能够为每个文章添加多个附件,并能够在临时目录中打开附件、导出附件。有道云的附件也存储在云端。

时间: 2024-10-11 16:34:26

主程序员的练成:TCP、消息分包和协议设计的相关文章

主程序员的练成:HTTP协议和二进制协议的对比

在上一篇<主程序员的练成:TCP.消息分包和协议设计>中谈了协议设计的一些话题,这里补充聊聊HTTP协议和二进制协议的对比. HTTP协议是一种文本协议,也是一种Name-Based协议,就从这两方面来说. 文本协议 vs 二进制协议 文本协议的特点: 便于人 易于阅读.理解.调试.构造 解析复杂.冗余多 需要考虑字符转义 二进制协议的特点: 便于机器 Name-Based vs Position-Based Name-Based协议的特点: 协议字段都用Name标识 协议字段与位置无关 协议

主程序员的练成:CGI和FastCGI

消息经过网络传输,到达了服务器端,最常见的服务器是Web服务器,做PHP的同学都知道FastCGI模式的PHP比普通PHP更高效,这篇就聊聊其中的原理. 古老但常见的CGI Web服务器能解析HTTP请求,返回静态资源(HTML页.图片等),但要输出动态内容,必须得PHP/C#/Ruby/Java/Python/C/C++这些外部程序来实现. 早期有个技术叫CGI(Common Gateway Interface,通用网关接口),是用于Web服务器和外部程序之间传输数据的一种标准.一个简单的CG

主程序员的练成:技术篇概要

技术是程序员安身立命的家伙,主程的技术不强,向下难以服众,向上有负重托. 或许有人会问:技术深度上该挖多深才能做好主程?程序员至少有两个高阶成长方向: 1.技术型专家非常热爱技术本身,往往会钻研得非常深,甚至可以不承担管理职责(你心目中的榜样是谁?): 2.项目型专家着力于更好更快的实现项目,主导项目的团队组建.技术选型.架构设计.项目进度和质量管理等等,技术深度上不像技术型专家那么深,一般承担管理职责. 主程属于项目型专家方向,对技术深度广度的要求是够用就好,我对程序开发持实用主义态度,80%

主程序员的练成──引言

虽然是引言,但也很重要. 程序员如何成长?这个话题百度有大约170万个相关结果,介绍了不少从菜鸟到老鸟的经验,但如何成长为主程序员(以下简称主程),网上的"帮助文档"不完善,也缺少实践指南.本系列文章主题就是说说主程如何练成.为什么用"练"这个字,因为主程的很多技能光知道怎么做远远不够,还需要在实践中不断"训练"才能运用好.只有不断训练才能从知到行,从"知道"成长为"做到". 团队在任命主程时,大多会挑选经

程序员每天累成狗,是为了什么

HI,想我了吗 了吗 了吗?自从上次情人节一别,我已经接近20天没更新文章了. 至于原因:是,办点其他私事,这一段压根没怎么联网,所以不太好意思,我也很想你们了.大家也不要问为什吗,辣么帅的人有什么事了,从今天开始我就正式回归了!还是那熟悉的节奏和风格,和帅帅的颜值 掌声响起来...啪啪啪 啪啪啪 这篇文章的起因有二点: 一.我这些天之所以没更新,不是因为我懒,是因为我确实很累和其他私事. 二.有许多人问我说:小北哥哥,感觉每天都很累,真不知道为什么,什么时候是个头! 我看我们的很多同行,都是一

CSDN日报20170311——《程序员每天累成狗,是为了什么》

[程序人生]程序员每天累成狗,是为了什么 作者:郭小北 程序员可以投入的资本就是:身体和脑力,说白了都是出卖劳动力换取回报,也就是钱.我们大部分人都是凡人,或许当初是基于兴趣和理想去做一件事,入一门行,但随着阅历的丰富,年龄的增长,责任感的叠加你工作就是为了钱啊,因为在这个物质的社会,你连家都养不了,何来生活的更好? [物联网]Android Things --SDK框架 作者:王玉成 物联网应用开发与手机和平板的应用开发有一些区别,那么Android Things与Android又有哪些差别呢

基于libevent的tcp拆包分包库

TCP/IP协议虽然方便,但是由于是基于流的传输(UDP是基于数据报的传输),无论什么项目,总少不了解决拆包分包问题. 以前的项目总是每个程序员自己写一套拆包分包逻辑,实现的方法与稳定性都不太一致.终于有了做基线的机会,自己写了一个基于libevent的拆包分包库. 本文档黏贴一些核心的内容. //回调接口 class ITcpPacketNotify{public:virtual void OnConnected(int fd) = 0;virtual void OnDisConnected(

NTCPMSG 开源高性能TCP消息发送组件

https://www.cnblogs.com/eaglet/archive/2013/01/07/2849010.html 目前的.net 架构下缺乏高效的TCP消息发送组件,而这种组件是构建高性能分布式应用所必需的.为此我结合多年的底层开发经验开发了一个.net 下的高效TCP消息发送组件.这个组件在异步发送时可以达到每秒160万包,而相同大小的数据包用WCF的TCP模式OneWay 方式发送每秒只能达到5.6万包. 项目首页 http://ntcpmsg.codeplex.com/ 功能介

标准口语就是这样疯狂得练成地

口语是这样练成地: 1.看一部有兴趣的电影,(180分钟到三个小时不等) 2.到处宣传此影片主角的迷人程度,陶醉其中,向亲朋好友强烈推荐,精彩片段重温,引导大家一起看,自己从旁讲解,并乐此不疲.(视业绩而定) 3.疯狂搜索其剧本,(一个晚上或一个下午) 4.下载剧本,(宽带几分钟) 5.整理剧本,(三到五个小时) 6.打印剧本,(几分钟,打印店离你家较远之类情况不在考虑范围之内) 7.看剧本,大声朗读,好东西啊!(三十分钟左右,长了嗓子受不了,地点最好选在阳台,以免打扰同学或亲人工作休息) 8.