白话TCP为什么需要进行三次握手

本文深入解析TCP/IP协议中三次握手的全过程,通过生动的现实生活例子,详细解释了三次握手的目的和重要性,确保客户端与服务器间建立可靠的双工连接。

640?wx_fmt=gif

640?wx_fmt=jpeg

Linux编程 点击右侧关注,免费入门到精通! 640?wx_fmt=jpeg


作者丨雨林

https://www.cnblogs.com/yuilin


640?wx_fmt=gif首先简单介绍一下TCP三次握手


在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。


第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;


第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器 进入SYN_RECV状态;


第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入 ESTABLISHED状态,完成三次握手。


通过这样的三次握手,客户端与服务端建立起可靠的双工的连接,开始传送数据。


三次握手的最主要目的是保证连接是双工的,可靠更多的是通过重传机制来保证的。


但是为什么一定要进行三次握手来保证连接是双工的呢,一次不行么?两次不行么?我们举一个现实生活中两个人进行语言沟通的例子来模拟三次握手。


640?wx_fmt=gif第一次对话:


老婆让甲出去打酱油,半路碰到一个朋友乙,甲问了一句:哥们你吃饭了么?


结果乙带着耳机听歌呢,根本没听到,没反应。甲心里想:跟你说话也没个音,不跟你说了,沟通失败。说明乙接受不到甲传过来的信息的情况下沟通肯定是失败的。


如果乙听到了甲说的话,那么第一次对话成功,接下来进行第二次对话。


640?wx_fmt=gif第二次对话:


乙听到了甲说的话,但是他是老外,中文不好,不知道甲说的啥意思也不知道怎样回答,于是随便回答了一句学过的中文 :我去厕所了。甲一听立刻笑喷了,“去厕所吃饭”?道不同不相为谋,离你远点吧,沟通失败。说明乙无法做出正确应答的情况下沟通失败。


如果乙听到了甲的话,做出了正确的应答,并且还进行了反问:我吃饭了,你呢?那么第二次握手成功。


通过前两次对话证明了乙能够听懂甲说的话,并且能做出正确的应答。接下来进行第三次对话。


640?wx_fmt=gif第三次对话:


甲刚和乙打了个招呼,突然老婆喊他,“你个死鬼,打个酱油咋这么半天,看我回家咋收拾你”,甲是个妻管严,听完吓得二话不说就跑回家了,把乙自己晾那了。乙心想:这什么人啊,得,我也回家吧,沟通失败。说明甲无法做出应答的情况下沟通失败。


如果甲也做出了正确的应答:我也吃了。那么第三次对话成功,两人已经建立起了顺畅的沟通渠道,接下来开始持续的聊天。


通过第二次和第三次的对话证明了甲能够听懂乙说的话,并且能做出正确的应答。

可见,两个人进行有效的语言沟通,这三次对话的过程是必须的。


同理对于TCP为什么需要进行三次握手我们可以一样的理解:


为了保证服务端能收接受到客户端的信息并能做出正确的应答而进行前两次(第一次和第二次)握手,为了保证客户端能够接收到服务端的信息并能做出正确的应答而进行后两次(第二次和第三次)握手。


640?wx_fmt=gif当然,还有一种更通俗的~


买手机的时候试通话功能的时候:


1老机打给新机 : 喂 , 听到了吗 ?


2新机回复老机 : 听到了 , 你听到了吗 ?


3老机 : 听到了听到了 …


验证通话功能OK !


 推荐↓↓↓ 

640?wx_fmt=png

?16个技术公众号】都在这里!

涵盖:程序员大咖、源码共读、程序员共读、数据结构与算法、黑客技术和网络安全、大数据科技、编程前端、Java、Python、Web编程开发、Android、iOS开发、Linux、数据库研发、幽默程序员等。

640?wx_fmt=png万水千山总是情,点个 “ 好看” 行不行
<think>好的,我现在需要回答用户关于输入输出流使用时需要注意的注意事项,并且要用白话解释。首先,我得回忆一下输入输出流的基本概念和相关知识点,然后结合用户提供的引用内容,看看有没有相关的信息可以利用。 首先,输入输出流(I/O流)是程序中处理数据输入和输出的重要部分,常见的注意事项包括资源管理、异常处理、缓冲区的使用、字符编码等。用户提到的引用中,引用[1]提到了日志输出必须使用条件输出或占位符,这可能与I/O操作中的性能或格式化有关;引用[2]涉及转义符的使用,这在处理字符串输出时需要注意;引用[4]提到编程语言和翻译器的内容,可能和编码有关联。 接下来,我需要把这些知识点整理成用户容易理解的白话解释,分点说明注意事项,每个注意事项尽量用例子或实际应用场景来解释。同时,要确保符合系统级指令,比如行内数学公式用$...$,独立公式用$$...$$,但可能这里用不上数学公式,所以重点在中文回答和结构清晰。 然后,生成相关问题。通常相关问题可以围绕注意事项的每个点展开,比如资源释放、异常处理、缓冲区的优化、字符编码问题等。 还需要检查引用内容,用户提供的引用中,引用[1]关于日志的条件输出,可能在I/O操作中如果频繁记录日志需要注意性能,使用占位符而不是拼接字符串;引用[2]的转义符在处理文件路径或输出特殊字符时需要正确使用;引用[4]可能涉及编码问题,比如不同语言的字符编码需要统一。 现在,把这些内容组织成结构化的回答,分点列出注意事项,每个点简单解释,并引用相关的引用内容。例如,资源释放可以提到不关闭流会导致资源泄漏,异常处理部分需要try-catch-finally或者在Java 7+使用try-with-resources,缓冲区则提到使用缓冲流提升效率,字符编码强调指定正确的编码避免乱码,路径处理注意转义符或使用正斜杠,大文件分块处理等。 最后,生成相关问题,可能包括如何正确关闭流、处理异常的方法、缓冲区的作用、字符编码问题解决方案、大文件处理技巧等。 检查是否符合所有系统级指令:中文回答,结构清晰,引用正确,没有使用任何markdown格式,分点明确,语言口语化,没有技术术语堆砌,确保用户容易理解。</think>输入输出流使用时需要注意以下事项,用白话解释如下: --- ### 1. **用完记得关!** 流用完后必须手动关闭(比如`.close()`),否则可能导致文件被占用无法操作,或者内存泄漏。 例如:文件读写完不关,其他程序就打不开这个文件。 ```java // 正确做法:在finally块中关闭流,或用Java 7+的try-with-resources try (FileInputStream fis = new FileInputStream("file.txt")) { // 操作流 } catch (IOException e) { e.printStackTrace(); } ``` --- ### 2. **异常要兜底** I/O操作可能遇到文件不存在、权限不足等问题,必须用`try-catch`捕获异常,避免程序崩溃。 例如:读取一个不存在的文件时,不处理异常程序会直接报错退出。 --- ### 3. **缓冲能加速** 直接读写文件效率低,用缓冲流(如`BufferedInputStream`)减少硬盘访问次数。 ```java // 缓冲流示例:用BufferedReader包装FileReader BufferedReader reader = new BufferedReader(new FileReader("file.txt")); ``` --- ### 4. **编码别乱码** 读写文本时明确指定字符编码(如UTF-8),否则中文可能变乱码。 例如:文件是UTF-8编码,但读取时用GBK,中文会显示成“��”。 --- ### 5. **路径小心斜杠** 文件路径中的反斜杠`\`需要转义(写成`\\`),或者直接用正斜杠`/`(系统自动兼容)。 例如:`"C:\\文件夹\\文件.txt"`或`"C:/文件夹/文件.txt"`[^2]。 --- ### 6. **大文件分块读** 读取大文件时不要一次性加载到内存,分块读取(比如用`byte[] buffer`)避免内存溢出。 ```java byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { // 处理每一块数据 } ``` --- ### 7. **输出内容格式化** 输出复杂内容时,用占位符或`String.format()`代替字符串拼接,提升可读性和性能[^1]。 例如:`System.out.printf("姓名:%s,年龄:%d", name, age);` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值