• 计算机网络再次整理————tcp的关闭[七]


    前言

    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 双向关闭就好。

    四次挥手的抓包。

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

  • 相关阅读:
    瀑布流布局——JS+绝对定位
    浏览器事件的思考
    css的hack详解
    主流浏览器的Hack写法
    [HTML&CSS] 未知高度多行文本垂直居中
    HTML标签的默认样式列表
    推荐的 CSS 书写顺序
    高效整洁CSS代码原则 (上)
    高效整洁CSS代码原则 (下)
    Xcode升级导致插件失效的解决办法
  • 原文地址:https://www.cnblogs.com/aoximin/p/15864326.html
Copyright © 2020-2023  润新知