说起TCP/IP协议,大家估计都能说出个一二,但是估计很少有人能够深入的理解这个协议,原因有这么几个:

  1. 协议本身确实复杂
  2. 入门教材没选对,太抽象了,导致大家浅尝辄止
  3. 学习过程中如果没有配合实践理解,过段时间也忘记了。

所以本篇文章的用意就是通过理论和实践的结合,加深大家对TCP协议的理解,更好的应用TCP来编写客户端和服务端。

TCP理论介绍

说到入门教材我比较推荐《图解TCP/IP》,本节内容也是在这本书的理论基础上结合自己的理解构成。
首先 TCP位于七层协议中的传输层。

TCP通信简单的说是类似这样的。

TCP协议是构建在网络层的IP协议之上的面向连接的、可靠的流协议。

TCP如何保证可靠性?

推荐使用WireShark抓包来学习TCP协议的特点,推荐一篇教程。由于HTTP协议是构建TCP协议之上的,所以可以用Wireshark对你的上网过程进行抓包,来观察TCP协议的流程和特性。

连接管理(三次握手)

上图是在HTTP GET之前,先经过了TCP的三次握手。
192.168.5.81 ——》 191.0.0.1 SYN(发起连接)
191.0.0.1 ——》 192.168.5.81 ACK(对192.168.5.81 的SYN的确认)+SYN(发起连接)
192.168.5.81 ——》 191.0.0.1 ACK(对191.0.0.1 的SYN的确认)

通过序列号与确认应答提高可靠性。

红圈部分是做个示例,TCP中的每一包数据都包含着自身的数据序列号(Sequence Number),以及已收到对方数据的确认号(Acknowledgement Number)。
以下是TCP的报文头定义,方便对照WireShark查看。

假如某包数据发送之后,迟迟未受到对方确认,则会进行超时重发。
假如重发一定次数之后,还是没有任何确认应答返回,就会判断网络或对端主机发生异常,强制关闭连接。
通过以上这个机制就可以保证数据不会存在丢包、顺序混乱的问题。

TCP以段为单位发送数据

参考Wireshark的截图,第一包数据中有个属性 MSS=1460(Maximum Segment Size最大消息长度,也就是所谓的“段”)。
以太网标准MSS是1460,同时两端的主机在发出建立连接的请求时会在TCP首部写入MSS选项,告诉对方自己的接口能够适应的MSS的大小。然后会在两者之间选择一个较小的值投入使用。

利用窗口控制提高速度 和 拥塞控制

TCP以段为单位收发数据,如果每发一个段都要进行确认的话效率有点低,于是TCP引入了窗口的概念。
窗口的大小就是指无需等待确认应答而可以继续发送数据的最大值。
在通信刚开始的时候窗口大小一般为1个段,后续随着通信的正常进行,窗口会变大,这叫做拥塞控制,主要是防止网络拥堵。因为计算机网络处在一个共享的环境中,如果大家一开始都采用最大量数据发送可能导致网络瘫痪。
下图红圈是每一个窗口确认的过程,可以看出来窗口是持续增大的。

流控制

TCP的流控制的意思就是通信双方会协商好传输数据的速度,否则一方数据发送太快,另一方数据处理能力有限就会导致数据丢弃,从而造成流量的浪费。
接收主机将自己可以接受的缓冲区大小放入到TCP首部字段通知给发送端。这个字段越大,说明网络的吞吐量越大。

OK,以上是TCP的一些基本概念和特性,讲的比较浅,算是自己的一个总结,说多了也不容易记住。
本篇文章先到这里,下一篇再介绍Socket API及其相关使用问题。

TCP编程实践小结1的更多相关文章

  1. Socket编程实践(6) --TCP服务端注意事项

    僵尸进程处理 1)通过忽略SIGCHLD信号,避免僵尸进程 在server端代码中添加 signal(SIGCHLD, SIG_IGN); 2)通过wait/waitpid方法,解决僵尸进程 sign ...

  2. C# socket编程实践

    C# socket编程实践——支持广播的简单socket服务器   在上篇博客简单理解socket写完之后我就希望写出一个websocket的服务器了,但是一路困难重重,还是从基础开始吧,先搞定C# ...

  3. [Python] 网络编程之TCP编程

    转自:TCP编程 - 廖雪峰的官方网站 Socket是网络编程的一个抽象概念.通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协 ...

  4. 牛客网Java刷题知识点之TCP、UDP、TCP和UDP的区别、socket、TCP编程的客户端一般步骤、TCP编程的服务器端一般步骤、UDP编程的客户端一般步骤、UDP编程的服务器端一般步骤

    福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号:   大数据躺过的坑      Java从入门到架构师      人工智能躺过的坑         Java全栈大联盟   ...

  5. Socket编程实践(6) --TCPNotes服务器

    僵尸进程过程 1)通过忽略SIGCHLD信号,避免僵尸进程 在server端代码中加入 signal(SIGCHLD, SIG_IGN); 2)通过wait/waitpid方法.解决僵尸进程 sign ...

  6. 高性能javascript学习笔记系列(5) -快速响应的用户界面和编程实践

    参考高性能javascript 理解浏览器UI线程  用于执行javascript和更新用户界面的进程通常被称为浏览器UI线程  UI线程的工作机制可以理解为一个简单的队列系统,队列中的任务按顺序执行 ...

  7. 高性能JavaScript 编程实践

    前言 最近在翻<高性能JavaScript>这本书(2010年版 丁琛译),感觉可能是因为浏览器引擎的改进或是其他原因,书中有些原本能提高性能的代码在最新的浏览器中已经失效.但是有些章节的 ...

  8. Java TCP编程

    Java编写TCP编程--回射信息实例 注:简单的tcp联系,还存在问题,readUTF()为阻塞型,如果之前的用户一直不输入,则一直阻塞,之后的用户再连接会出现问题. import java.io. ...

  9. Method Swizzling和AOP(面向切面编程)实践

    Method Swizzling和AOP(面向切面编程)实践 参考: http://www.cocoachina.com/ios/20150120/10959.html 上一篇介绍了 Objectiv ...

随机推荐

  1. Solr定时导入功能实现

    需要实现Solr定时导入功能的话,我们可以通过使用Solr自身所集成的dataimportscheduler调度器实现 下载对应的jar包,下载地址https://code.google.com/ar ...

  2. .net 资源释放(托管资源和非托管资源)

    1.托管资源 像int.float.DateTime等都是托管资源:net中80%的资源都是托管资源: 托管资源的回收通过GC(垃圾回收器)自动释放分配给该对象的内存,但无法预测进行垃圾回收的时间,我 ...

  3. Android Studio导入第三方jar包或依赖工程的方法

    Android Studio导入第三方jar包或依赖工程的方法   一 导入jar包的方法 1.打开自己的工程,将需要导入的jar包copy到libs文件夹下 2.在导入的jar包处单击菜单 Add ...

  4. HQL-Query接口

    org.hibernate.Query接口 1.Query接口定义有执行查询的方法(完成HQL语句的解析和执行过程并返回查询结果,就像SQL语句没了JDBC接口就成了一个普通的字符串变量) 2.Que ...

  5. 别人的Linux私房菜(10)vim程序编辑器

    很多软件的编辑接口会主动调用vi vi分一般命令模式.编辑模式.命令行模式. 使用vi :/bin/vi welcome.txt 下下端显示文本有多少行,多少字符, 一般命令模式: 上下左右移动光标k ...

  6. 关于java poi itext生成pdf文件的例子以及方法

    最近正在做导出pdf文件的功能,所以查了了一些相关资料,发现不是很完善,这里做一些小小的感想,欢迎各位“猿”童鞋批评指正. poi+itext,所需要的jar包有itext-2.1.7.jar,poi ...

  7. (PMP)第9章-----项目资源管理

    9.1 规划资源管理 数据表现: 1.层级型(高层次的角色):工作分解结构,组织分解结构,资源分解结构 2.责任分配矩阵:RAM,RACI,执行,负责,咨询,知情(只有一个A) 3.文本型(记录详细职 ...

  8. 容器启动脚本报错:exec user process caused "no such file or directory"

    1.现象 standard_init_linux.go:: exec user process caused "no such file or directory" 2.原因 原因 ...

  9. Windows激活客户端 已停止工作

    win+r 进入运行 slmgr /ipx 新的sn slmgr /ato

  10. Python开发——7.迭代器、生成器和装饰器

    一.迭代器 1.迭代器协议 (1)迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么引起一个StopIteration移除异常以中止迭代. (2)可迭代对象:实现了迭 ...