TCP编程实践小结1
说起TCP/IP协议,大家估计都能说出个一二,但是估计很少有人能够深入的理解这个协议,原因有这么几个:
- 协议本身确实复杂
- 入门教材没选对,太抽象了,导致大家浅尝辄止
- 学习过程中如果没有配合实践理解,过段时间也忘记了。
所以本篇文章的用意就是通过理论和实践的结合,加深大家对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的更多相关文章
- Socket编程实践(6) --TCP服务端注意事项
僵尸进程处理 1)通过忽略SIGCHLD信号,避免僵尸进程 在server端代码中添加 signal(SIGCHLD, SIG_IGN); 2)通过wait/waitpid方法,解决僵尸进程 sign ...
- C# socket编程实践
C# socket编程实践——支持广播的简单socket服务器 在上篇博客简单理解socket写完之后我就希望写出一个websocket的服务器了,但是一路困难重重,还是从基础开始吧,先搞定C# ...
- [Python] 网络编程之TCP编程
转自:TCP编程 - 廖雪峰的官方网站 Socket是网络编程的一个抽象概念.通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协 ...
- 牛客网Java刷题知识点之TCP、UDP、TCP和UDP的区别、socket、TCP编程的客户端一般步骤、TCP编程的服务器端一般步骤、UDP编程的客户端一般步骤、UDP编程的服务器端一般步骤
福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号: 大数据躺过的坑 Java从入门到架构师 人工智能躺过的坑 Java全栈大联盟 ...
- Socket编程实践(6) --TCPNotes服务器
僵尸进程过程 1)通过忽略SIGCHLD信号,避免僵尸进程 在server端代码中加入 signal(SIGCHLD, SIG_IGN); 2)通过wait/waitpid方法.解决僵尸进程 sign ...
- 高性能javascript学习笔记系列(5) -快速响应的用户界面和编程实践
参考高性能javascript 理解浏览器UI线程 用于执行javascript和更新用户界面的进程通常被称为浏览器UI线程 UI线程的工作机制可以理解为一个简单的队列系统,队列中的任务按顺序执行 ...
- 高性能JavaScript 编程实践
前言 最近在翻<高性能JavaScript>这本书(2010年版 丁琛译),感觉可能是因为浏览器引擎的改进或是其他原因,书中有些原本能提高性能的代码在最新的浏览器中已经失效.但是有些章节的 ...
- Java TCP编程
Java编写TCP编程--回射信息实例 注:简单的tcp联系,还存在问题,readUTF()为阻塞型,如果之前的用户一直不输入,则一直阻塞,之后的用户再连接会出现问题. import java.io. ...
- Method Swizzling和AOP(面向切面编程)实践
Method Swizzling和AOP(面向切面编程)实践 参考: http://www.cocoachina.com/ios/20150120/10959.html 上一篇介绍了 Objectiv ...
随机推荐
- C++ static 静态变量&静态成员函数
.h文件中定义 static变量后,如 static QTcpSocket * socket; 那么一定要在.cpp中 构造函数的外面将其初始化为 QTcpSocket * Cfiletransfer ...
- C++ 提取网页内容系列之一
标 题: C++ 提取网页内容系列作 者: itdef链 接: http://www.cnblogs.com/itdef/p/4171179.html 欢迎转帖 请保持文本完整并注明出处 首先分析网页 ...
- 20170805_Elasticsearch_简介和安装
官网地址: https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started.html Elk 是一个可高 ...
- java多线程系列10 阻塞队列模拟
接下来的几篇博客会介绍下juc包下的相关数据结构 包含queue,list,map等 这篇文章主要模拟下阻塞队列. 下面是代码 import java.util.LinkedList; import ...
- 1.4eigen中的块运算
1.4 块运算 块是矩阵或数组的一个矩形部分.块表达式既可以做左值也可以作右值.和矩阵表达式一样,块分解具有零运行时间成本,对你的程序进行优化. 1.使用块运算 最常用的块运算是.block()成员函 ...
- #10072. 「一本通 3.2 例 1」Sightseeing Trip(floyd求最小环+路径)
https://loj.ac/problem/10072 针对无向图 因为Floyd是按照结点的顺序更新最短路的,所以我们在更新最短路之前先找到一个连接点k,当前的点k肯定不存在于已存在的最短路f[i ...
- 工具SQL
1.数据库设计文档维护SQL SELECT COLUMN_NAME 列名, COLUMN_TYPE 数据类型, DATA_TYPE 字段类型, CHARACTER_MAXIMUM_LENGTH 长度, ...
- vue全局后置钩子afterEach
beforeEach是路由跳转前执行的,afterEach是路由跳转后执行的. afterEach只有两个参数 afterEach((to,from)=>{}) 例子: router.afte ...
- MySQL中校验规则(collation)的选取对实际数据筛选的影响
在mysql中存在着各种utf8编码格式,如下表:1)utf8_bin2)utf8_general_ci utf8_bin将字符串中的每一个字符用二进制数据存储,区分大小写.utf8_genera_c ...
- 桌面管理工具 RedisDesktopManager 0.8.8
RedisDesktopManager 0.8.8 发布,此版本更新内容如下: 改进: Show key bytes length and value bytes length #3677 修复: ...