• 程序员修神之路--简约而不简单的分布式通信基石


    分布式系统可以总结为是处于不同物理位置的多个进程组成的整体,为了确保这个整体有效并且高效的对外提供服务,每个节点之间都有可能需要进行通信来交换信息,而这个交换信息的过程多数使用的是tcp协议。tcp协议是位于ip层之上的传输层协议,在这个传输层里有两个比较重要的协议:tcp和udp。对于应用层的开发人员来说,用的最多的就是这两个协议,这也是一些面试官必问的知识点之一

    无论是tcp还是udp,都是建立在ip+端口的规则之上,什么意思呢?也就是说采用tcp和udp的进程都需要一个端口来读取和写入数据。

    TCP协议

    tcp协议是可靠的协议,而且是面向连接的,建立连接的过程会经过三次握手。为什么会是三次握手而不是二次或者四次呢?

    image

    说到这个问题,可以抽象出一个场景,怎么样才能确定一端是和另外一端互通的呢?其实很简单,一端发送给另一端的消息能顺利给我答复,这就说明两端是联通的。tcp协议的三次握手恰好说明了这一点,A和B通信,只要三次握手,A能得到B的答复,B也能得到A的答复。

    基于ip层发送的报文,在网络中是无法确定是否正确到达对方的。tcp协议在ip协议之上添加了一系列数据结构和算法来保证tcp的数据正确到达。

    1. tcp的数据包是有编号的,这么做主要是为了解决顺序问题,如果没有编号,对方怎么确定顺序呢?另外一点,编号是为了发送方来确认哪些包已经正确到达对方
    2. 当tcp的数据包被接收方接收,接收方需要发送确认包给发送方,发送方在接收到确认包之后会把对应的数据包做状态修改,由于每个数据包其实有超时机制,在超时之后,发送方会进行重试
    3. tcp是面向字节流的,发送的时候发的是一个字节流,这是tcp自己的状态维护的事情。

    说了这么多,其实可以把tcp看做是一个有状态的协议,它可以根据网络状况,对方接收情况等诸多因素来调整自己的发送状态。

    UPP协议

    相对于tcp协议来说,udp要简单很多

    1. udp协议不需要建立连接,这就意味着发送方只要知道对方的ip和端口,就可以发送,基于这一点可以做广播。
      2.udp协议不负责可靠交付,因为它不像tcp协议那样有一堆的算法和数据结构来做保证。
    2. udp是基于数据报形式的,一个一个的发,一个一个的接收。而且udp数据的发送不会根据因为网络环境的阻塞而改变

    udp基于以上特性可以在网络环境比较好或者对于丢包不敏感的应用中使用。udp在舍弃了重传,顺序等一些列特性之后,处理速度特别快,在一些不敏感但是实时性要求比较高的场景中应用非常广泛。

    Socket

    在有了tcp和udp协议之后,进程间通信的基石就有了。但是总不能每次通信自己都需要写tcp的三次握手等这些复杂过程吧。为了屏蔽这些复杂的过程,使通信程序简单,在tcp和udp协议之上,便抽象出来了socket这个概念。

    所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议根进行交互的接口

    socket是区分服务端和客户端的,本地的socket与远程的一个socket建立连接的过程,其实就是tcp协议三次握手的过程。一旦socket连接建立,就可以利用socket抽象出来的read或者write方法来进行通信了。

    socket需要指定使用的IP协议,还需要指定使用的是tcp还是udp协议。基于tcp协议的服务端的socket需要bind一个端口来listen并且accept客户端的socket连接。这也是服务端socket和客户端socket的一个区别。
    image

    对于udp来说,过程有点不一样。udp是没有连接的,一是不需要三次握手,二是不需要listen和connect,但是仍然需要ip和端口bind,要不然远端的数据到来的时候,系统会找不到接收程序的。UDP是没有连接状态的,因而不需要每次连接都建立一组Socket,而是只用一个Socket,就能够和多个客户端通信。也正是因为没有连接状态,每次通信的时候,调用sendto和recvfrom,都需要传入 IP 地址和端口。

    image

    基于tcp的socket在内核中都有一个发送缓冲区和接收缓冲区,tcp的双工工作模式以及tcp的滑动窗口就是依赖于这两个独立的buffer以及buffer的数据填充状态。接收缓冲区把数据缓存入内核之中,如果对应的应用一直没有调用socket的read方法进行数据读取,则此数据会一直被缓存在接收缓冲区中,如果接收缓冲区满了,便会通知对方socket,以调整对方socket的发送窗口大小,这就是滑动窗口的实现。如果对方仍然持续发送数据,接收方在接收缓冲区没有被读取的情况下将丢弃后到的数据,这就是tcp的流量控制。对于udp来说,它没有真正的发送缓冲区,只要有数据就会发送,无论对方能否正常正确接收,这也是udp丢包的原因之一,但是udp的socket 和tcp的socket一样都会有接收缓冲区,而且行为也一样。

    写在最后

    有的面试官吹水,号称http长连接,这个说法其实是不准确的,长连接和短连接是针对tcp协议而言,http只是建立在tcp/ip协议之上的应用层的一个协议。总体而言,tcp和udp设计的数据结构和算法有很多,这里只是粗略的说了一下,有兴趣的同学可以去研究tcp协议那本书。

  • 相关阅读:
    java类中为什么设置set和get方法操作属性
    Java常用排序算法+程序员必须掌握的8大排序算法+二分法查找法
    自学Zabbix之路15.3 Zabbix数据库表结构简单解析-Triggers表、Applications表、 Mapplings表
    自学Zabbix之路15.2 Zabbix数据库表结构简单解析-Items表
    自学Zabbix之路15.1 Zabbix数据库表结构简单解析-Hosts表、Hosts_groups表、Interface表
    21 Zabbix系统性能优化建议
    20 Zabbix 利用Scripts栏目对Hosts远程执行命令
    19 Zabbix web监控实例
    18 Zabbix 新增map中的icon图标
    自学Zabbix3.12.6-动作Action-Escalations配置
  • 原文地址:https://www.cnblogs.com/zhanlang/p/13357643.html
Copyright © 2020-2023  润新知