技术教程 第2页

Linux常用基础命令三-CDN-服务器-VPS优惠/促销/测评-撸主机评测

Linux常用基础命令三

一、ln 软链接 软链接也被称为符号链接,类似于 windows 快捷方式,有自己的数据块,主要存储 链接其他文件的路径。 在查看文件目录时,软连接是l’开头 创建软链接 ln -s [原文件或目录或文件名] [软链接名] —–(功能描述:为原文件创建软链接) 删除软链接 rm -rf 软链接名 注意: 而不是 rm -rf 软链接名/ ,如果使用 rm -rf 软链接名/ 删除软链接对应的真实目录 ,不删除目录 扩展:硬链接,不加-s ln [原文件或目录或文件名] [软链接名] —–(功能描述:为原文件创建软链接) 二、history历史命令已经执行 基本语法 history ——(功能描述:查看已执行的历史命令) 查询近n条历史指令 history n 清空历史指令 history -c 三、时间命令 获取系统当前时间 date 格式化语法 (1)date (功能描述:显示当前时间) (2)date %Y (功能描述:显示当前年份) (3)date %m (功能描述:显示当前月份) (4)date %d (功能描述:显示当前哪一天) (5)date ” %Y-%m-%d %H:%M:%S” (功能描述:显示年、月、分秒) %s 代表是时间戳 %S 代表秒 显示前一天 date -d ‘1 days ago’ (功能描述:显示前一天) 显示明天 date -d ‘-1 days ago’ (功能描述:显示明天时间) 显示前一小时 date -d ‘1 hours ago’ (功能描述:显示前一天) 显示后一小时 date -d ‘-1 hours ago’ (功能描述:显示前一天) 设置系统时间 date -s ”2032-01-01 12:00:00 ” 查看日历 cal —当前月 cal -3 —-当月,前后一个月 查看今年的日历 cal -y 查看一年的全年日历 cal 2023 —-以后直接命令加年 调整日历的周显示 cal -m ——每月星期一排名第一 cal -s —–每个月的周日排名第一...

Linux常用基础命令-CDN-服务器-VPS优惠/促销/测评-撸主机评测

Linux常用基础命令

一、系统目录结构 约定俗成:   bin (binaries)存放二进制可执行文件   sbin (super user binaries)存放二进制可执行文件,只有root才能访问   etc (etcetera)存放系统配置文件   usr (unix shared resources)用于存放共享的系统资源   home 存放用户文件的根目录   root 超级用户目录   dev (devices)用于存放设备文件   lib (library)存放跟文件系统中的程序运行所需要的共享库及内核模块   mnt (mount)系统管理员安装临时文件系统的安装点   boot 存放用于系统引导时使用的各种文件   tmp (temporary)用于存放各种临时文件   var (variable)用于存放运行时需要改变数据的文件 二、基本命令 1.目录操作 相对路径和绝对路径说明: 现在在/home/dijia478/下 ./a/b.txt和a/b.txt都表示相对路径,当前目录下的a文件夹下的b.txt文件 /home/dijia478/a/b.txt表示绝对路径,根目录下的home文件夹下的dijia478文件夹下的a文件夹下的b.txt文件 cd ./a 切换到当前目录的a文件夹 cd ..  切换到上一层目录 cd /  切换到系统根目录 cd ~  切换到用户主目录 cd -  切换到上一个所在目录 pwd  显示当前所在目录的绝对路径 2.查看文件列表 ls /path/显示该目录所有文件或文件夹名 ls -a  显示所有文件或文件夹名(包含隐藏的) ls -l  按列表显示所有文件或文件夹,缩写成ll ll -h  友好的显示文件大小(显示成K,MB,GB) 3.创建和删除文件夹 mkdir app  创建app文件夹 mkdir –p app2/test  级联创建aap2以及test文件夹 rmdir app  删除app目文件夹(需要是空文件夹) 4.文件操作 rm a.txt  删除a.txt文件,删除需要用户确认,y/n rm -f a.txt  不询问,直接删除a.txt文件 rm -r a  递归删除a文件夹(无论是否有内容) rm -rf a  不询问递归删除a文件夹(慎用) rm -rf *  删除当前目录下所有内容(***别用) rm -rf /*  no 作 no die(Linux系统就玩完了) cp a.txt b.txt  将a.txt复制为b.txt文件 cp a.txt ../  将a.txt文件复制到上一层目录中 mv a.txt ../  将a.txt文件移动到上一层目录中 mv a.txt b.txt  将a.txt文件重命名为b.txt touch a.txt  创建一个空的a.txt文件 echo “good good study” > a.txt  把”>”左边的输出内容放到右边的文件里去,如果存在就覆盖,如果不存在就创建 vi a.txt  用文本编辑器编辑一个文件,如果不存在就创建 5.文件打包归档和压缩 tar -cvf file.tar dirpath filepath  将dir文件夹和file文件在当前目录下打包成file.tar tar –xvf file.tar  解包到当前目录 gzip file.tar  压缩文件或文件夹 gzip...

服务器禁Ping后怎么强行看延迟?-CDN-服务器-VPS优惠/促销/测评-撸主机评测

服务器禁Ping后怎么强行看延迟?

在linux环境下进行源码安装 在本站提供的百度网盘备用下载地址中找到文件tcping-1.3.5-for-linux.tar.gz 准备安装环境,需要安装gcc: # RHEL/CentOS5-6-7版本使用yum安装gcc与make yum -y install gcc make # RHEL8/CentOS8使用dnf安装gcc与make dnf -y install gcc make # Ubuntu/Debian使用apt安装gcc与make apt -y install gcc make 开始解压并编译tcping-1.3.5-for-linux.tar.gz # 解压缩tcping-1.3.5源代码 tar -xf tcping-1.3.5-for-linux.tar.gz # 进入解压缩tcping-1.3.5的路径 cd tcping-1.3.5 # 开始编译tcping-1.3.5 make #反馈显示 gcc -o tcping -Wall -DHAVE_HSTRERROR tcping.c 编译结束 # 将编译好的tcping放置到/usr/local/bin/下 cp tcping /usr/local/bin/ # 然后在控制台直接打tcping即可使用,想要查看tcping使用方法可以参见 tcping –help   1.3 在linux环境下使用python-pip进行安装 这个步骤就非常简单了,无需手动下载任何文件。 准备安装环境,需要安装python-pip: # RHEL/CentOS5-6-7使用yum安装Python-pip yum -y install python-pip # RHEL8/CentOS8使用dnf安装Python-pip dnf -y install python-pip # Ubuntu/Debian使用apt安装Python-pip apt -y install python-pip   # 使用Python-pip进一步安装 pip install tcping # 反馈 Successfully installed click-7.0 tcping-0.1.1rc1 安装完成   二、详细介绍tcping如何使用 在本地主机和远程主机之间,tcping可以测试出执行TCP三次握手所需的时间(SYN,SYN / ACK,ACK)。最终ACK传送时间不包括在内,只有最少的时间才能将其丢弃在近端。 由于tcping的Linux源代码年久失修,tcping目前仅在Windows模式下提供强大的功能支持,Linux模式下仅提供基本功能支持。 # Windows下使用 tcping [参数选项] [目标主机地址] [端口] # Linux下使用(参数较少) tcping [目标主机地址] -p [端口] 下面以Windows下的tcping为例,详解相关选项和参数: 选项 -4,优先使用IPv4 -6,优先使用IPv6 -h,使用http模式 -t,让命令持续运行,直到使用ctrl + c指令退出 -n 数字,发送命令的次数,默认4次 -i 数字,发送ping命令的时间间隔,默认1s,可以为小数...

vps服务器搭建教程(自己搭建内网穿透服务器)-CDN-服务器-VPS优惠/促销/测评-撸主机评测

vps服务器搭建教程(自己搭建内网穿透服务器)

即将开始返工潮,很多跨境公司也要开始正常业务了。 首当其冲的就是网络问题、Vultr还是很稳定的,而且相对也比较简单一些。所以问题不多,但是用阿里云、腾讯云、Amazon云的相对问题就会多一些,很多去年的IP肯定会被墙掉,这是正常的。 我们这里以腾讯云为例子,举例说一下怎么样去处理。 没必要老是重新购买新的vps服务器,这样其实拿到的,还是众多有问题的ip,不划算的,不如针对问题来进行修改。这样其实更稳定一些。 1、ip不能用了,我们要确定一下是ip被墙,还是端口被墙。不要盲目的去删除,重装系统。简单的方法,就是直接ping 一下ip地址:     如果这个地方没有断,正常的。但是不能访问网络,证明ip一般是没什么问题的,只是端口被墙掉了。这个时候,我们只需要换一个端口就行了。连接好服务器之后,只需要输入:bash ssr.sh 而不是其他那些一长串的,更不要用安装代码那些了。     我们就可以进入菜单选项了。     然后直接 选择第9项,就行了。 这样处理一下,基本上就没问题了。 2、如果已经ping不能了,而且也访问不了 。证明这个ip已经彻底被搞掉了。那么我们怎么办?很多人第一反应是删除服务器,重新开新的。其实不是这样的。我们可以只换ip就行了。很多服务商都可以做到的。我们以腾讯云为例子:     直接 选择这里的更换公网ip就可以了,自动重新分配一个新的ip给你,你的配置,所有的一切都不会变。可以节省相当多的精力了。然后输入新的ip,或者重新进入服务器去获取最新的地址就行了。     每个云服务可能有不同的次数限制、但是一般来说够用的。这里是以天为单,什么意思呢?就是明天我还是可以换ip的,是不是很不错呢。我看好多人反复开通、删除,付款、退款。好麻烦。节省一点精力去facebook研究上吧。 3、还有很多人碰到,电脑可以用,手机不能用的情况。排查的时候、有一个地方要注意,就是安全组。有很多人会制定很多条款、去手动开很多端口,其实没那么复杂。一条就行。     开启所有的端口就行了。 还有一点就是,大环境,全民远程云办公,对这些云服务商的压力很大。这也是出问题的一部分原因。电脑连接成功之后,手机连接耐心等待一下,还有就是手机可以重启一下。这样成功率高很多。成功之后,就不要随意去弄了。频繁的断网,其实在某些时候会被当成攻击存在的。因为每一个云服务商其实都有巡查机制。你触发了而已。

大数据开发:Kafka日志结构-CDN-服务器-VPS优惠/促销/测评-撸主机评测

大数据开发:Kafka日志结构

Kafka作为大数据技术生态的重要组件,尤其是实时流数据处理场景下,作为分布式生产/消费系统,得到广泛的重用。而Kafka在数据生产和消费上,日志是主要的场景。今天的大数据开发学习分享,我们就来讲讲kafka日志结构的基础。 Kafka消息是以主题为单位,主题之间相互独立。每个主题又由一个或多个分区构成,分区数可以在创建主题时指定,也可以在主题创建后再修改,但只能增加一个主题的分区数而不能减少其分区数。每个分区可以有一个或多个副本。 在存储结构上分区的每个副本对应一个Log对象,每个Log又划分为多个LogSegment,每个LogSegment包括一个日志文件和两个索引文件,其中两个索引文件分别为偏移量索引文件和时间戳索引文件。Log对象中维护了一个ConcurrentSkipListMap,底层是一个跳跃表,保存该主题所有分区对应的所有LogSegment。日志文件和索引文件与磁盘上的物理存储文件相对应。 Kafka将日志文件封装为一个FileMessageSet对象,将两个索引文件封装为OffsetIndex和TimeIndex对象。 1.数据文件 数据文件用来存储消息,每条消息由一个固定长度的消息头和一个可变长度的消息体数据组成。消息体包括一个可变长度的消息Key和消息实际数据Value,消息Key可以为空,消息结构如下图所示: 消息结构各字段说明: CRC32:CRC32校验和 magic:kafka服务程序协议版本号 attributes:低两位用来表示压缩方式,第三位表示时间戳类型,高4位预留 timestamp:消息时间戳,当magic大于0时消息头必须包含该字段 key-length:消息key的长度 key:消息key实际数据 payload-length:消息体实际数据长度 payload:消息体实际数据 在实际存储时一条消息总长度还包括12字节额外的开销,其中8字节长度记录消息的偏移量,消息的偏移量是相对该分区下第一个数据文件的基准偏移量而言,用来确定消息在分区下的逻辑位置,同一个分区下的消息偏移量按序递增,另外4字节表示消息总长度。因此在0.10.1版本Kafka一条消息的固定长度为34字节,所以在数据文件中相邻两条消息的position值之差减去34,即为消息Key和消息数据Value的总长度。 数据文件的大小由配置项log.segment.bytes指定,默认为1GB。同时Kafka提供了根据时间来切分日志段的机制,即使数据文件大小没有达到log.segment.bytes设置的阈值,但达到了log.roll.ms或是log.roll.hours设置的阈值,同样会创建新的日志段,在磁盘上创建一个数据文件和两个索引文件。接收消息追加操作的日志段也称为活跃段activeSegment。 2.偏移量索引文件 为了提高查找效率,Kafka为每个数据文件创建了一个基于偏移量的索引文件,数据文件同名,后缀为.index。 偏移量索引文件用来存储索引,索引是用来将偏移量映射成消息在数据文件中的物理位置,每个索引条目由offset和position组成,每个索引条目唯一确定数据文件中的一条消息。索引条目的offse和position与数据文件中消息的offse和position一一对应的,例如,数据文件中某条消息为offset:8和position:0,若为该条消息创建了索引,索引文件中索引值为offset:8和position:0。 并不是每条消息都对应有索引,kafka采用了稀疏存储的方式,每隔一定字节的数据建立一条索引,可以通过index.interval.bytes设置索引跨度。 每次写消息到数据文件时会检查是否要向索引文件写入索引条目,创建一个新索引条目的条件为:距离前一次写索引后累计消息字节数大于index.interval.bytes配置值。具体实现是LogSegment维持一个int类型的变量bytesSinceLastIndexEntry,初始值为0,每次写消息时先判断该值是否大于索引跨度。若小于索引跨度,则将该条消息的字节长度累加到变量bytesSinceLastIndexEntry中;否则会为该条消息创建一个索引条目写入索引文件,然后将bytesSinceLastIndexEntry重置为0。 3.时间戳索引文件 时间戳索引文件与数据文件同名,以.timeindex后缀,该索引文件包括一个8字节长度的时间戳字段和一个4字节的偏移量字段,其中时间戳记录的是该日志段目前为止最大时间戳,偏移量则记录的是插入新的索引条目时,当前消息的偏移量。 该索引文件索引条目之间的跨度由index.interval.bytes设置的阈值决定,但同时必须保证新创建的索引条目的时间戳大于上一个索引的时间戳。 时间戳索引也采用了稀疏存储的方式,索引条目对应的时间戳的值及偏移量与数据文件中相应消息的这两个字段的值相同。同时在记录偏移量索引条目时会判断是否需要同时写时间戳索引。 关于大数据学习,Kafka日志结构,以上就为大家做了基本的讲解了。Kafka在实时消息流的生产和消费上,其稳定性和可靠性,依赖于存储,对于日志结构这部分,建议大家一定要理解透彻。

数据结构的三要素-CDN-服务器-VPS优惠/促销/测评-撸主机评测

数据结构的三要素

数据结构主要关注逻辑结构、数据的运算和物理结构(存储结构)。 01 逻辑结构 集合结构和数学中的集合概念类似,各个元素同属一个集合。 线性结构的元素像一条线。 树形结构的元素就像一棵树,常见的思维导图、文件夹展开的目录都是树形结构。 图结构像一张网。 02 数据的运算 数据的运算其实就是大家熟悉的增删改查,不过相比数据库现成的SQL,数据结构实现起来有很多细节需要考虑。 03 物理结构 物理结构是计算机存储的结构。 比如线性结构在底层需要物理结构来实现。 顺序存储把元素按顺序存储起来,这样元素的线性结构就体现出来了。 链式存储通过存储下一个元素的地址表示出元素间的线性结构。 索引存储用一张索引表来查出元素在内存中的位置。 散列存储没有索引表,而是根据元素的关键字直接计算出该元素的存储地址,很厉害。 ,

图文并茂,33张图解ReentrantReadWriteLock源码!-CDN-服务器-VPS优惠/促销/测评-撸主机评测

图文并茂,33张图解ReentrantReadWriteLock源码!

纵观全局 我的英文名叫ReentrantReadWriteLock(后面简称RRW),大家喜欢叫我读写锁,因为我常年混迹在读多写少的场景。 image.png 读写锁规范 作为合格的读写锁,先要有读锁与写锁才行。 所以声明了ReadWriteLock接口,作为读写锁的基本规范。 image.png 之后都是围绕着规范去实现读锁与写锁。 读锁与写锁 WriteLock与ReadLock就是读锁和写锁,它们是RRW实现ReadWriteLock接口的产物。 但读锁、写锁也要遵守锁操作的基本规范. 所以WriteLock与ReadLock都实现了Lock接口。 image.png 那么WriteLock与ReadLock对Lock接口具体是如何实现的呢? 自然是少不了我们的老朋友AQS了。 AQS 众所周知,要实现锁的基本操作,必须要仰仗AQS老大哥了。 AQS(AbstractQueuedSynchronizer)抽象类定义了一套多线程访问共享资源的同步模板,解决了实现同步器时涉及的大量细节问题,能够极大地减少实现工作,用大白话来说,AQS为加锁和解锁过程提供了统一的模板函数,只有少量细节由子类自己决定。 AQS简化流程图如下 image.png Sync AQS为加锁和解锁过程提供了统一的模板函数,只有少量细节由子类自己决定,但是WriteLock与ReadLock没有直接去继承AQS。 因为WriteLock与ReadLock觉得,自己还要去继承AQS实现一些两者可以公用的抽象函数,不仅麻烦,还有重复劳动。 所以干脆单独提供一个对锁操作的类,由WriteLock与ReadLock持有使用,这个类叫Sync。 Sync继承AQS实现了如下的核心抽象函数 tryAcquire release tryAcquireShared tryReleaseShared image 其中tryAcquire、release是为WriteLock写锁准备的。 tryAcquireShared、tryReleaseShared是为ReadLock读锁准备的,这里阿星后面会说。 上面说了Sync实现了一些AQS的核心抽象函数,但是Sync本身也有一些重要的内容,看看下面这段代码 image 我们都知道AQS中维护了一个state状态变量,正常来说,维护读锁与写锁状态需要两个变量,但是为了节约资源,使用高低位切割实现state状态变量维护两种状态,即高16位表示读状态,低16位表示写状态。 Sync中还定义了HoldCounter与ThreadLocalHoldCounter HoldCounter是用来记录读锁重入数的对象 ThreadLocalHoldCounter是ThreadLocal变量,用来存放第一个获取读锁线程外的其他线程的读锁重入数对象 image.png 公平与非公平策略 你看,人家ReentrantLock都有公平与非公平策略,所以ReentrantReadWriteLock也要有。 什么是公平与非公平策略? 因为在AQS流程中,获取锁失败的线程,会被构建成节点入队到CLH队列,其他线程释放锁会唤醒CLH队列的线程重新竞争锁,如下图所示(简化流程)。 image.png 非公平策略是指,非CLH队列的线程与CLH队列的线程竞争锁,大家各凭本事,不会因为你是CLH队列的线程,排了很久的队,就把锁让给你。 公平策略是指,严格按照CLH队列顺序获取锁,一定会让CLH队列线程竞争成功,如果非CLH队列线程一直占用时间片,那就一直失败,直到时间片轮到CLH队列线程为止,所以公平策略的性能会更差。 image.png 回到正题,为了支持公平与非公平策略,Sync扩展了FairSync、NonfairSync子类,两个子类实现了readerShouldBlock、writerShouldBlock函数,即读锁与写锁是否阻塞。 image.png 关于readerShouldBlock、writerShouldBlock函数在什么地方使用阿星后面会说。 ReentrantReadWriteLock全局图 最后阿星把前面讲过的内容,全部组装起来,构成下面这张图。 image.png 有了全局观后,后面就可以深入细节逐个击破了。 深入细节 后面我们只要攻破5个细节就够了,分别是读写锁的创建、获取写锁、释放写锁、获取读锁、释放读锁。 ReentrantReadWriteLock的创建 读写锁的创建,会初始化化一系列类,代码如下 image.png ReentrantReadWriteLock默认是非公平策略,如果想用公平策略,可以直接调用有参构造器,传入true即可。 但不管是创建FairSync还是NonfairSync,都会触发Sync的无参构造器,因为Sync是它们的父类(本质上它们俩都是Sync)。 image.png 因为Sync需要提供给ReadLock与WriteLock使用,所以创建ReadLock与WriteLock时,会接收ReentrantReadWriteLock对象作为入参。 image.png 最后通过ReentrantReadWriteLock.sync把Sync交给了ReadLock与WriteLock。 获取写锁 我们遵守ReadWriteLock接口规范,调用ReentrantReadWriteLock.writeLock函数获取写锁对象。 image.png 获取到写锁对象后,遵守Lock接口规范,调用lock函数获取写锁。 WriteLock.lock函数是由Sync实现的(FairSync或NonfairSync)。 image.png sync.acquire(1)函数是AQS中的独占式获取锁流程模板(Sync继承自AQS)。 image.png WriteLock.lock调用链如下图 image.png 我们只关注tryAcquire函数,其他函数是AQS的获取独占式锁失败后的流程内容,不属于本文范畴,tryAcquire函数代码如下 image.png 为了易于理解,阿星把它转成流程图 image.png 通过流程图,我们发现了一些要点 读写互斥 写写互斥 写锁支持同一个线程重入 writerShouldBlock写锁是否阻塞实现取决公平与非公平的策略(FairSync和NonfairSync) 释放写锁 获取到写锁,临界区执行完,要记得释放写锁(如果重入多次要释放对应的次数),不然会阻塞其他线程的读写操作,调用unlock函数释放写锁(Lock接口规范)。 WriteLock.unlock函数也是由Sync实现的(FairSync或NonfairSync)。 image.png sync.release(1)执行的是AQS中的独占式释放锁流程模板(Sync继承自AQS)。 image.png WriteLock.unlock调用链如下图 image.png 再来看看tryRelease函数,其他函数是AQS的释放独占式成功后的流程内容,不属于本文范畴,tryRelease函数代码如下 image.png 为了易于理解,阿星把它转成流程图 image.png 因为同一个线程可以对相同的写锁重入多次,所以也要释放的相同的次数。 获取读锁 我们遵守ReadWriteLock接口规范,调用ReentrantReadWriteLock.readLock函数获取读锁对象。 ![ image.png sync.acquireShared(1)函数执行的是AQS中的共享式获取锁流程模板(Sync继承自AQS)。 image.png ReadLock.lock调用链如下图 image.png 我们只关注tryAcquireShared函数,doAcquireShared函数是AQS的获取共享式锁失败后的流程内容,不属于本文范畴,tryAcquireShared函数代码如下 image.png 代码还挺多的,为了易于理解,阿星把它转成流程图 image.png 通过流程图,我们发现了一些要点 读锁共享,读读不互斥 读锁可重入,每个获取读锁的线程都会记录对应的重入数 读写互斥,锁降级场景除外 支持锁降级,持有写锁的线程,可以获取读锁,但是后续要记得把读锁和写锁读释放 readerShouldBlock读锁是否阻塞实现取决公平与非公平的策略(FairSync和NonfairSync) 释放读锁 获取到读锁,执行完临界区后,要记得释放读锁(如果重入多次要释放对应的次数),不然会阻塞其他线程的写操作,通过调用unlock函数释放读锁(Lock接口规范)。 ReadLock.unlock函数也是由Sync实现的(FairSync或NonfairSync)。 image.png sync.releaseShared(1)函数执行的是AQS中的共享式释放锁流程模板(Sync继承自AQS)。...

TCP的三次握手与四次挥手-CDN-服务器-VPS优惠/促销/测评-撸主机评测

TCP的三次握手与四次挥手

简介 TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议,在发送数据前,通信双方必须在彼此间建立一条连接。所谓的“连接”,其实是客户端和服务端保存的一份关于对方的信息,如ip地址、端口号等。TCP可以看成是一种字节流,它会处理IP层或以下的层的丢包、重复以及错误问题。在连接的建立过程中,双方需要交换一些连接的参数。这些参数可以放在TCP头部。一个TCP连接由一个4元组构成,分别是两个IP地址和两个端口号。一个TCP连接通常分为三个阶段:连接、数据传输、退出(关闭)。通过三次握手建立一个链接,通过四次挥手来关闭一个连接。当一个连接被建立或被终止时,交换的报文段只包含TCP头部,而没有数据。 1. TCP报文的头部结构 在了解TCP连接之前先来了解一下TCP报文的头部结构。 图片 上图中有几个字段需要重点介绍下: (1)序号:seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。 (2)确认序号:ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,ack=seq+1。 (3)标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义如下: ACK:确认序号有效。 FIN:释放一个连接。 PSH:接收方应该尽快将这个报文交给应用层。 RST:重置连接。SYN:发起一个新连接。 URG:紧急指针(urgent pointer)有效。需要注意的是:不要将确认序号ack与标志位中的ACK搞混了。确认方ack=发起方seq+1,两端配对。 2. 三次握手 三次握手的本质是确认通信双方收发数据的能力首先,我让信使运输一份信件给对方,对方收到了,那么他就知道了我的发件能力和他的收件能力是可以的。于是他给我回信,我若收到了,我便知我的发件能力和他的收件能力是可以的,并且他的发件能力和我的收件能力是可以。然而此时他还不知道他的发件能力和我的收件能力到底可不可以,于是我最后回馈一次,他若收到了,他便清楚了他的发件能力和我的收件能力是可以的。这,就是三次握手。 图片 第一次握手:客户端要向服务端发起连接请求,首先客户端随机生成一个起始序列号ISN(比如是100),那客户端向服务端发送的报文段包含SYN标志位(也就是SYN=1),序列号seq=100。 第二次握手:服务端收到客户端发过来的报文后,发现SYN=1,知道这是一个连接请求,于是将客户端的起始序列号100存起来,并且随机生成一个服务端的起始序列号(比如是300)。然后给客户端回复一段报文,回复报文包含SYN和ACK标志(也就是SYN=1,ACK=1)、序列号seq=300、确认号ack=101(客户端发过来的序列号+1)。 第三次握手:客户端收到服务端的回复后发现ACK=1并且ack=101,于是知道服务端已经收到了序列号为100的那段报文;同时发现SYN=1,知道了服务端同意了这次连接,于是就将服务端的序列号300给存下来。然后客户端再回复一段报文给服务端,报文包含ACK标志位(ACK=1)、ack=301(服务端序列号+1)、seq=101(第一次握手时发送报文是占据一个序列号的,所以这次seq就从101开始,需要注意的是不携带数据的ACK报文是不占据序列号的,所以后面第一次正式发送数据时seq还是101)。当服务端收到报文后发现ACK=1并且ack=301,就知道客户端收到序列号为300的报文了,就这样客户端和服务端通过TCP建立了连接。 3. 四次挥手 四次挥手的目的是关闭一个连接 图片 比如客户端初始化的序列号ISA=100,服务端初始化的序列号ISA=300。TCP连接成功后客户端总共发送了1000个字节的数据,服务端在客户端发FIN报文前总共回复了2000个字节的数据。 第一次挥手:当客户端的数据都传输完成后,客户端向服务端发出连接释放报文(当然数据没发完时也可以发送连接释放报文并停止发送数据),释放连接报文包含FIN标志位(FIN=1)、序列号seq=1101(100+1+1000,其中的1是建立连接时占的一个序列号)。需要注意的是客户端发出FIN报文段后只是不能发数据了,但是还可以正常收数据;另外FIN报文段即使不携带数据也要占据一个序列号。 第二次挥手:服务端收到客户端发的FIN报文后给客户端回复确认报文,确认报文包含ACK标志位(ACK=1)、确认号ack=1102(客户端FIN报文序列号1101+1)、序列号seq=2300(300+2000)。此时服务端处于关闭等待状态,而不是立马给客户端发FIN报文,这个状态还要持续一段时间,因为服务端可能还有数据没发完。 第三次挥手:服务端将最后数据(比如50个字节)发送完毕后就向客户端发出连接释放报文,报文包含FIN和ACK标志位(FIN=1,ACK=1)、确认号和第二次挥手一样ack=1102、序列号seq=2350(2300+50)。 第四次挥手:客户端收到服务端发的FIN报文后,向服务端发出确认报文,确认报文包含ACK标志位(ACK=1)、确认号ack=2351、序列号seq=1102。注意客户端发出确认报文后不是立马释放TCP连接,而是要经过2MSL(最长报文段寿命的2倍时长)后才释放TCP连接。而服务端一旦收到客户端发出的确认报文就会立马释放TCP连接,所以服务端结束TCP连接的时间要比客户端早一些。 4. 常见面试题 为什么TCP连接的时候是3次?2次不可以吗? 因为需要考虑连接时丢包的问题,如果只握手2次,第二次握手时如果服务端发给客户端的确认报文段丢失,此时服务端已经准备好了收发数(可以理解服务端已经连接成功)据,而客户端一直没收到服务端的确认报文,所以客户端就不知道服务端是否已经准备好了(可以理解为客户端未连接成功),这种情况下客户端不会给服务端发数据,也会忽略服务端发过来的数据。如果是三次握手,即便发生丢包也不会有问题,比如如果第三次握手客户端发的确认ack报文丢失,服务端在一段时间内没有收到确认ack报文的话就会重新进行第二次握手,也就是服务端会重发SYN报文段,客户端收到重发的报文段后会再次给服务端发送确认ack报文。 为什么TCP连接的时候是3次,关闭的时候却是4次? 因为只有在客户端和服务端都没有数据要发送的时候才能断开TCP。而客户端发出FIN报文时只能保证客户端没有数据发了,服务端还有没有数据发客户端是不知道的。而服务端收到客户端的FIN报文后只能先回复客户端一个确认报文来告诉客户端我服务端已经收到你的FIN报文了,但我服务端还有一些数据没发完,等这些数据发完了服务端才能给客户端发FIN报文(所以不能一次性将确认报文和FIN报文发给客户端,就是这里多出来了一次)。 为什么客户端发出第四次挥手的确认报文后要等2MSL的时间才能释放TCP连接? 这里同样是要考虑丢包的问题,如果第四次挥手的报文丢失,服务端没收到确认ack报文就会重发第三次挥手的报文,这样报文一去一回最长时间就是2MSL,所以需要等这么长时间来确认服务端确实已经收到了。

SpringBoot的全局异常处理的优雅吃法!要进来学习下吗-CDN-服务器-VPS优惠/促销/测评-撸主机评测

SpringBoot的全局异常处理的优雅吃法!要进来学习下吗

SpringBoot全局异常准备 开发准备 环境要求 JDK :1.8 SpringBoot :1.5.17.RELEASE 首先还是Maven的相关依赖: 1<properties><project.build.sourceencoding>UTF-8</project.build.sourceencoding><java.version>1.8</java.version><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><parent><groupid>org.springframework.boot</groupid>spring-boot-starter-parent<version>1.5.17.RELEASE</version><relativepath></relativepath></parent><dependencies><dependency><groupid>org.springframework.boot</groupid>spring-boot-starter-web</dependency><dependency><groupid>org.springframework.boot</groupid>spring-boot-starter-test<scope>test</scope></dependency><dependency><groupid>com.alibaba</groupid>fastjson<version>1.2.41</version></dependency></dependencies> 配置文件这块基本不需要更改,全局异常的处理只需在代码中实现即可。 代码编写 SpringBoot的项目已经对有一定的异常处理了,但是对于我们开发者而言可能就不太合适了,因此我们需要对这些异常进行统一的捕获并处理。SpringBoot中有一个 ControllerAdvice 的注解,使用该注解表示开启了全局异常的捕获,我们只需在自定义一个方法使用 ExceptionHandler 注解然后定义捕获异常的类型即可对这些捕获的异常进行统一的处理。 我们根据下面的这个示例来看该注解是如何使用吧。 示例代码: 123456789@ControllerAdvice public class MyExceptionHandler {     @ExceptionHandler(value =Exception.class)  public String exceptionHandler(Exception e){   System.out.println("未知异常!原因是:"+e);         return e.getMessage();     } } 上述的示例中,我们对捕获的异常进行简单的二次处理,返回异常的信息,虽然这种能够让我们知道异常的原因,但是在很多的情况下来说,可能还是不够人性化,不符合我们的要求。那么我们这里可以通过自定义的异常类以及枚举类来实现我们想要的那种数据吧。 自定义基础接口类 首先定义一个基础的接口类,自定义的错误描述枚举类需实现该接口。 代码如下: 1234567public interface BaseErrorInfoInterface {     /** 错误码*/   String getResultCode();    /** 错误描述*/   String getResultMsg(); } 自定义枚举类 然后我们这里在自定义一个枚举类,并实现该接口。 代码如下: 1234567891011121314151617181920212223242526272829303132public enum CommonEnum implements BaseErrorInfoInterface {  // 数据操作错误定义  SUCCESS("200", "成功!"),  BODY_NOT_MATCH("400","请求的数据格式不符!"),  SIGNATURE_NOT_MATCH("401","请求的数字签名不匹配!"),  NOT_FOUND("404", "未找到该资源!"),  INTERNAL_SERVER_ERROR("500", "服务器内部错误!"),  SERVER_BUSY("503","服务器正忙,请稍后再试!")  ;  /** 错误码 */  private String resultCode;  /** 错误描述 */  private String resultMsg;  CommonEnum(String resultCode, String resultMsg) {   this.resultCode = resultCode;   this.resultMsg = resultMsg;  }  @Override  public String getResultCode() {   return resultCode;...

登录

找回密码

注册