前言

tcp的关闭不是简单粗暴的,相对而言是友好优雅的,好聚好散吧。

那么友好的关闭方式是这样的:

假设这里是客户端请求关闭的,服务端倒过来。

客户端:我要请求关闭

服务端:我接收到你的请求了,等我把要发的数据发完。

服务端:我要发的数据发完了,可以关闭了。

客户端:好的,我已经执行清理工作了,关闭结束。

那么这个时候为什么服务端直接告诉客户端可以直接关闭了呢?

为什么服务器端要做一些事情呢,到底有啥用。

回到设计的角度上,理论上是越简单越好的,遇到了什么问题,才使得我们要增加一个步骤呢。

那么就开始介绍到底发送了什么事情,这要从。。。。

正文

为什么会有四次挥手呢?

网上有很多故事哈。

下面其中一个故事是:

答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

下面自我整理一下。

为什么要有挥手这个操作呢?

本质上要回到tcp是流的这种操作上。

流有什么特点呢?就是不知道什么时候结束。

那么进行假如客户端发送数据完毕后,那么就需要告诉服务端发送完毕了。

服务端也需要告诉客户端收到了客户端的信号了,告诉客户端我已经知道你发送结束了。这就两次挥手了。

但是tcp其实是一对一的,双向通信的,你客户端发送完毕了,服务端不一定数据发送完毕啊。

那么客户端应该还在接收消息,tcp应该是半关闭了。

那么服务端发送数据完毕后,也应该给客户端一次挥手,告诉客户端:服务端已经发送完毕了,这就3次挥手了。

客户端应该也给服务端发送信号,自己收到了服务端结束数据传输了,你如果不给服务端传输,那么服务端也不知道你信号收到了。

那么其实四次挥手也就是因为tcp是流的这个特性了,因为要告诉对方,流结束了,对方也要回应流结束标志收到了。

具体实现就是下面这个了:

这里顺便说一下为什么tcp连接要三次握手呢? 这是因为tcp是双向通信了。

A->B 请求连接,那么说明A->B 是能够通信的。

但是B可不一定能到A,因为有防火墙等,那么B 就要发送信息给 A,既是告诉B能收到B的信息,也是试探一些B是否能发送给A。

那么A收到B的数据后,那么也得回应一下啊,不然B也不知道能发送信息到A啊。这就三次握手了。

实验代码服务端:

// See https://aka.ms/new-console-template for more information

using System.Net;
using System.Net.Sockets; var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var ipAddress = IPAddress.Parse("127.0.0.1");
EndPoint endPoint = new IPEndPoint(ipAddress, 8888);
socket.Bind(endPoint);
socket.Listen();
var clientSocket = socket.Accept();
while (true)
{
Console.WriteLine("开始接收");
var receiveMessage = new Byte[1000];
var size = clientSocket.Receive(receiveMessage);
if (size == 0)
{
clientSocket.Close();
break;
}
else
{
Console.WriteLine("接收到消息");
Console.WriteLine("receive message is:"+System.Text.Encoding.UTF8.GetString(receiveMessage));
}
}

实验代码客户端:

// See https://aka.ms/new-console-template for more information

using System.Net;
using System.Net.Sockets; var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var ipAddress = IPAddress.Parse("127.0.0.1");
EndPoint endPoint = new IPEndPoint(ipAddress, 8888);
socket.Connect(endPoint);
socket.Send(System.Text.Encoding.UTF8.GetBytes("hello service"));
Console.WriteLine("发送成功");
socket.Shutdown(SocketShutdown.Send);
Console.ReadLine();

上面客户端调用Shutdown关闭自己的发送端。

因为服务端不发送消息,直接收到客户端的传输完成信号后,直接close 双向关闭就好。

四次挥手的抓包。

介绍网络的一些周边之类的,比如域名、网络地址套接字的一些其他选项。

计算机网络再次整理————tcp的关闭[七]的更多相关文章

  1. 计算机网络再次整理————tcp周边[八]

    前言 tcp的包的格式可以看我以前的计算机网络整理,下面这些周边只是为了开发时候我们能用到一些理论知识. 正文 首先要介绍的就是域名,为啥有域名这东西呢?单纯站在网络的角度上讲这属于应用层的东西了. ...

  2. 计算机网络再次整理————tcp例子第二前奏[四]

    前言 前文我们介绍了网络协议的各层,同时也介绍了一下我们在编写代码时候的服务端的accept.bind.listen.connect.send做了什么. 可以说是从宏观的角度,或者代码开发的角度来说的 ...

  3. 计算机网络再次整理————tcp例子[五]

    前言 本文介绍一些tcp的例子,然后不断完善一下. 正文 服务端: // See https://aka.ms/new-console-template for more information us ...

  4. 计算机网络再次整理————tcp[二]

    前言 本文不会去介绍tcp的具体协议,因为这个tcp 应该不能说是单纯的连接和传输数据这么简单,里面还有很多机制. 正文 首先介绍一下什么是协议族(protocal Family),举个例子PF_IN ...

  5. 计算机网络再次整理————tcp例子前奏[三]

    前言 简单编写一下tcp例子. 正文 我们常说IOS有7层,实际上也只有4层,或者这样说简单的说是4层. 首先是数据链路层,首先这一层解决了什么问题呢?为什么要有这一层呢? 首先要抛开有操作系统的意识 ...

  6. 计算机网络再次整理————UDP例子[六]

    前言 简单的说,UDP 没有 TCP 用的广泛,但是还有很多是基于UDP的程序的,故而简单介绍一下. 正文 秉承节约脑容量的问题,只做简单的介绍和例子,因为自己几乎也没怎么用过UDP. 只是了解和知晓 ...

  7. 计算机网络再次整理————socket[一]

    前言 以前也整理过吧,写了几篇之后,感觉没啥整理的必要了然后就放弃了,最近又想整理一下. 正文 这篇对应的是:https://www.cnblogs.com/aoximin/p/12235333.ht ...

  8. 计算机网络基础之TCP/IP 协议栈

    计算机网络基础之TCP/IP 协议栈 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.TCP/IP 协议栈概述 1>.什么是TCP/IP协议栈 Transmission C ...

  9. TCP连接关闭总结

    由于涉及面太广,只作简单整理,有兴趣的可参考<UNIX Networking Programming>volum 1, Section 5.7, 5.12, 5.14, 5.15, 6.6 ...

随机推荐

  1. 使用.NET 6开发TodoList应用(13)——实现查询分页

    系列导航及源代码 使用.NET 6开发TodoList应用文章索引 需求 查询中有个非常常见的需求就是后端分页,实现的方式也不算复杂,所以我们本文仅仅演示一个后端查询分页的例子. 目标 实现分页查询返 ...

  2. 使用 jQuery 操作页面元素的方法,实现浏览大图片的效果,在页面上插入一幅小图片,当鼠标悬停到小图片上时,在小图片的右侧出现与之相对应的大图片

    查看本章节 查看作业目录 需求说明: 使用 jQuery 操作页面元素的方法,实现浏览大图片的效果,在页面上插入一幅小图片,当鼠标悬停到小图片上时,在小图片的右侧出现与之相对应的大图片 实现思路: 在 ...

  3. Oracle中的基本数据类型

    一.Oracle 基本数据类型 1.字符数据类型 CHAR:存储固定长度的字符串,如果没有指定长度,默认为1个字节,如果数据长度没有达到指定的长度,则通过填充空格的方式来使其达到定义的长度(CHAR类 ...

  4. Java高效开发-fiddler抓包工具

    1.简介 Fiddler是最常用的抓包工具之一,只要打开之后就能够实现数据包抓取,关闭之后会自动取消代理,非常方便本地调试 2.下载 阿里云盘地址:https://www.aliyundrive.co ...

  5. nginx之location、inmp架构详解、BBS项目部署

    本期内容概要 location lnmp架构 部署BBS项目 内容详细 1.location 使用Nginx Location可以控制访问网站的路径 但一个server可以有多个location配置 ...

  6. 『无为则无心』Python函数 — 33、高阶函数

    目录 1.高阶函数的定义 2.体验高阶函数 3.内置高阶函数 (1)map()函数 (2)reduce()函数 (3)filter()函数 1.高阶函数的定义 把函数作为参数传入(把一个函数作为另外一 ...

  7. Selenium_模拟键盘和鼠标操作(9)

    模拟键盘键盘和鼠标操作主要使用到selenium的keys包,源码如下 class Keys(object): """ Set of special keys codes ...

  8. spring boot & maven 多模块 ---心得

    1.前言 有个名字叫 多模块企业级项目  ,其实就是一个父级maven工程里面有着多个子级maven工程的项目 ,甚至在子级maven 里面还有多个子级maven, 这用到了 maven多模块开发的使 ...

  9. 简单的sdn防火墙

    github仓库 演示视频 本次实验建立的拓扑 使用到的 pox 指令介绍,参考pox控制器学习笔记 1. forwarding.l2_learning 使OpenFlow交换机充当L2学习交换机的一 ...

  10. CentOS6.5安装Hive-1.2.2

    注:图片如果损坏,点击文章链接:https://www.toutiao.com/i6627669615377908231/ Hadoop环境已安装完成<CentOS6.5下安装Hadoop-2. ...