zoukankan      html  css  js  c++  java
  • 主程的晋升攻略(4):TCP、消息分包和协议设计

    在《主程的晋升攻略(3):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协议是一种文本协议(非二进制协议)。用 来切割消息头和消息体,HTTP请求的消息头中有Content-Length来告知消息体有多大,假设没有该字段就表示无消息体,GET请求大多是这样。HTTP响应的消息头中,或者有Content-Length,或者有Transfer-Encoding: chunked告知以chunk模式分析消息体。
    HTTP请求


    HTTP响应1:Conetent-Length




    HTTP响应2:Transfer-Encoding



    HTTP用 来切割消息头和消息体,这样的用特定字符/字符串来切割或分包的方式。还有不少协议用到。比如FTP/SMTP/POP3都是用 来作为一个命令结束的标志。这样的消息分包的方式,须要应用层去扫描已recv到的数据,性能上还不够高效,代码不严谨的还easy被攻击。在须要自己定义协议的项目中。不少选择用二进制协议,解析高效,安全性更好些。



    最简单的二进制协议分包方式是消息的头4个字节表示消息的总长度。这样的方式还须要对最大消息长度做个限制。比如64K或1024K大小,避免超大数据包对接收方缓冲区的破坏。更进一步的。能够增加简单校验方法。

    比如消息头1个字节固定式0x2,消息的最后1个字节固定式0x3。消息总长度放在第2~5字节。这样收到完整消息后。假设头尾不是0x2和0x3,就直接异常处理。



    协议设计

    消息分包是协议设计的一个工作,协议设计的话题还不少,这里以HTTP协议为例。简要的说说里面设计的点。自己设计的协议也能够对比着有选择的使用,原理是共通的。

    由消息头+消息体组成:空行切割HTTP head和body,HTTP头的每一行以 结尾,空行就是
    消息分包:如上所述。HTTP用Content-Length和Transfer-Encodeing来分包
    消息压缩:请求中有Accept-Encoding字段。响应中用Content-Encoding字段表明压缩方式,一般採用gzip压缩
    消息加密:https  (SSL: Secure Socket Layer)
    消息ID:URL就是消息ID
    响应的状态码:第一个数字定义了响应的类别。
        1xx:指示信息--表示请求已接收,继续处理
        2xx:成功--表示请求已被成功接收、理解、接受
        3xx:重定向--要完毕请求必须进行更进一步的操作
        4xx:client错误--请求有语法错误或请求无法实现
        5xx:server端错误--server未能实现合法的请求
    协议版本号号: HTTP/1.1中的1.1就是HTTP 1.1版本号
    长连接:请求中Connection: keep-alive表示希望server保持连接,降低TCP连接的开销
    字符集: Content-Type字段表明了字符集。比如: Content-Type: text/html; charset=gb2312
    字符转义:URL中的參数须要做URL转义处理,比如http://xx.com/do?

    name=t%2F%3F%23%3Daa表示name为t/?

    #=aa

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



    -------- 切割线 ---------
    主程的晋升攻略(1):重要的引言
    主程的晋升攻略(2):技术篇概要
    主程的晋升攻略(3):IP、DNS和CDN
    主程的晋升攻略(5):HTTP协议和二进制协议的对照
    主程的晋升攻略(6):CGI和FastCGI


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


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


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


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


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


    ★ 【文章附件】可以为每一个文章加入多个附件,并可以在暂时文件夹中打开附件、导出附件。有道云的附件也存储在云端。



  • 相关阅读:
    linux如何编译安装新内核支持NTFS文件系统?(以redhat7.2x64为例)
    RAID磁盘阵列的搭建(以raid0、raid1、raid5、raid10为例)
    linux专题一之文件归档和压缩(tar、file、zip)
    linux专题一之文件管理(目录结构、创建、查看、删除、移动)
    CENTOS6.6上搭建单实例ORACLE12C
    oracle12c各个版本对其需要的依赖包及系统参数的修改
    mysql cp复制和mysqldump备份测试
    mysql之mysql_config_editor
    CENTOS6.6下redis3.2集群搭建
    CENTOS6.6 下mysql MHA架构搭建
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/6937228.html
Copyright © 2011-2022 走看看