计算机网络(1)- TCP
- TCP的全称是传输控制协议(Transmission Control Protocol)[RFC 793]
- TCP提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。TCP不提供广播或多播服务。由于TCP要提供可靠的、面向连接的服务,因此不可避免地增加了许多的开销,如确认、流量控制、计时器以及连接管理等。这不仅使协议数据单元的首部增大很多,还要占用许多的处理机资源。
- TCP最主要的特点:
- TCP是面向连接的传输层协议。即应用程序在使用TCP协议之前,必须先建立TCP连接。在传送数据完毕后,必须释放已经建立的TCP连接。
- 每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的。
- TCP提供可靠交付的服务。通过TCP连接传送的数据,无差错、不丢失、不重复并且按序到达。
- TCP提供全双工通信。TCP允许通信双方的应用进程在任何时候都能发送数据。TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据。在发送时,应用程序在吧数据传送给TCP的缓存后,就可以做自己的事,而TCP在合适的时候把数据发送出去。在接收时,TCP把收到的数据放入缓存,上层的应用进程在合适的时候读取缓存中的数据。
- 面向字节流。TCP中的“流(stream)”指的是流入到进程或从进程流出的字节序列。“面向字节流”的含义是,虽然应用程序和TCP的交互式是一次一个数据块(大小不等),但TCP把应用程序交下来的数据仅仅看成是一连串无结构的字节流。TCP并不知道所传送的字节流的含义。
4.TCP的连接
TCP把连接作为最基本的抽象。TCP连接的端点叫做套接字或插口。
每一条TCP连接唯一地被通信两端的两个端点(即两个套接字)所确定。即:
TCP连接 ::= {socket1,socket2} = {(IP1:port1),(IP2:port2)}
5.TCP报文段的首部格式
TCP虽然是面向字节流的,但TCP传送的数据单元却是报文段。一个TCP报文段分为首部和数据两部分,而TCP的全部功能都体现在它首部中各字段的作用。
TCP报文段首部的前20个字节是固定的,后面有4n字节是根据需要而增加的选项。因此TCP首部的最小长度是20字节。
6.TCP的运输连接管理
(1)TCP的连接建立
假设主机A运行的TCP客户程序,而B运行的是TCP服务器程序。最初两端的TCP进程都处于CLOSED(关闭)状态。A主动打开连接,而B被动打开连接。
连接过程:
初始状态:B的TCP服务器进程先创建传输控制块TCB,准备接受客户进程的连接请求。然后服务器进程就处于LISTEN(收听)状态,等待客户的连接请求。如有,即作出响应
- 在打算建立TCP连接时,向B发出连接请求报文段,这是首部中的同步位SYN = 1,同时选择一个初始序号seq = x。这时TCP客户进程进入SYN-SENT(同步已发送)状态。
- B收到连接请求报文段后,如同意建立连接,则向A发送确认。在确认报文段中应把SYN位和ACK位都置1,确认号是ack=x+1,同时也为自己选择一个初始序号seq=y。这是TCP服务器进程进入SYN-RCVD(同步收到)状态。
- TCP客户进程收到B的确认后,还要向B给出确认。确认报文段的ACK置1,确认号ack=y+1,而自己的序号seq=x+1。这时,TCP连接已经建立,A进入ESTABLISHED(已建立连接)状态。
连接建立后的状态:当B收到A的确认后也进入ESTABLISHED(已建立连接)状态。
问题1:为什么A最后还要发送一次确认呢?
是为了防止已失效的连接请求报文段突然又传送到了B,因而产生错误。
解释:假设A发出连接请求,但因连接请求报文丢失而未收到确认。于是,A再重传一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接。A共发送了两个连接 请求报文段,其中第一个丢失,第二个到达了B,此时没有“已失效的连接请求报文段”。假设A发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,以致延 误到连接释放之后的某个时间才到达B。本来这是一个早已失效的报文段,但B收到此失效的连接请求报文段后,就误以为是A又发出一次新的连接请求。于是就向A发出确认报文 段,同意建立连接。假如不采用三次握手,即没有最后一次连接确认,那么只要B向A发出同意连接请求,新的连接就建立了。然而由于此时A并没有发出建立连接的请求,因此不会 理睬B的确认,也不会向B发送数据。但B却以为新的运输连接已经建立了,并一直等待A发来的数据。B的许多资源就这样白白浪费了。
(2)TCP的连接释放
TCP连接释放的过程:
初始过程:数据传输结束后,通信的双方都可释放连接。现在A和B都处于ESTABLISHED状态。A的应用进程现象器TCP发出连接释放报文段,并停止发送数据,主动关闭TCP连接。
- A把连接释放报文段首部的终止控制位FIN=1,其序号seq=u,u等于前面A已传送过的数据的最后一个字节的序号加1。这是A进入FIN-WAIT1(终止等待1)状态,等待B的确认。
- B收到连接释放报文段后即发出确认,确认号是ack=u+1,其序号seq=v,v等于B前面已传送过的数据的最后一个字节的序号加1。然后B进入CLOSE-WAIT(关闭等待)状态。TCP服务器进程这时应通知高层应用进程,因而从A到B这个方向的连接就释放了,这时的TCP连接处于半关闭状态,即A已经没有数据要发送了,但B若发送数据,A仍要接收,也就是说,从B到A这个方向的连接并未变比,这个状态可能会持续一段时间。A收到来自B的确认后,就进入FIN-WAIT-2(终止等待-2状态),等待B发出的连接释放报文段。
- 若B已经没有要向A发送的数据了,其应用进程就通知TCP释放连接。这时B发出的连接释放报文段必须使FIN=1。先假定B的序号为w(在半关闭状态B可能又发送了一些数据)。B还必须重复上次已发送过的确认号ack = u + 1.这时B就进入LAST-ACK(最后确认)状态,等待A确认。
- A在收到B的连接释放报文段后,必须对此发出确认。在确认报文段中把ACK = 1,确认号ack = w + 1,而自己的序号是seq = u + 1。然后进入到TIME-WAIT(时间等待状态),必须经过时间等待计时器设置的时间2MSL(MSL叫做最长报文段寿命)后,A才进入到CLOSED状态。
连接释放后的状态:B收到A的报文后也进入到CLOSED状态。
问题1:为什么A在TIME-WAIT状态必须等待2MSL的时间呢?
保证A发送的最后一个ACK报文段能够到达B。
防止已失效的连接请求报文段出现在连接中。
解释:
第一,为了保证A发送的最后一个ACK报文段能够到达B。这个ACK报文段有可能丢失,因为使处在LAST-ACK状态的B收不到对已发送的FIN + ACK报文段的确认。B会超时重传这个FIN + ACK报文段,而A就能在2MSL时间内收到这个重传的FIN + ACK报文段。接着A重传一次确认,重新启动2MSL计时器。最后,A和B都正常进入到CLOSED状态。如果A在TIME-WAIT状态不等待 一段时间,而是在发送完ACK报文段后立即释放连接,那么就无法收到B重传的FIN + ACK报文段,因为也不会再发送一次确认报文段。这样,B就无法按照正常步骤进入CLOSED状态。
第二,防止“已失效的连接请求报文段” 出现在本连接中。A在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,这样就可 以使下一个新的连接中不会出现这种旧的连接请求报文段。
7.使用tcpdump分析tcp连接过程
场景:同一个局域网下,192.168.131.138上运行着apache2服务器(默认端口为80),同时apache2服务器上有大小为64KB的文件,名称为file64KB。
192.168.132.132上使用脚本,不停地运行wget http://192.168.131.138/file64KB去不停地下载192.168.131.138上的文件。
在192.168.131.132上运行tcpdump tcp -i ens33 -n命令,抓包。抓包结果如下:
::11.163215 IP 192.168.131.132. > 192.168.131.138.: Flags [S], seq , win , options [mss ,sackOK,TS val ecr ,nop,wscale ], length
::11.163355 IP 192.168.131.138. > 192.168.131.132.: Flags [S.], seq , ack , win , options [mss ,sackOK,TS val ecr ,nop,wscale ], length
::11.163390 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.163458 IP 192.168.131.132. > 192.168.131.138.: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP: GET /file_64KB HTTP/1.1
::11.163569 IP 192.168.131.138. > 192.168.131.132.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.163787 IP 192.168.131.138. > 192.168.131.132.: Flags [.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP: HTTP/1.1 OK
::11.163813 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.163848 IP 192.168.131.138. > 192.168.131.132.: Flags [.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.163862 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.163969 IP 192.168.131.138. > 192.168.131.132.: Flags [.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.163975 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.164011 IP 192.168.131.138. > 192.168.131.132.: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.164014 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.164038 IP 192.168.131.138. > 192.168.131.132.: Flags [.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.164043 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.164062 IP 192.168.131.138. > 192.168.131.132.: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.164065 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.164098 IP 192.168.131.138. > 192.168.131.132.: Flags [.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.164112 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.164149 IP 192.168.131.138. > 192.168.131.132.: Flags [.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.164154 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.164180 IP 192.168.131.138. > 192.168.131.132.: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.164183 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.164485 IP 192.168.131.132. > 192.168.131.138.: Flags [F.], seq , ack , win , options [nop,nop,TS val ecr ], length
::11.164863 IP 192.168.131.138. > 192.168.131.132.: Flags [F.], seq , ack , win , options [nop,nop,TS val ecr ], length
::11.164882 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length ::11.168172 IP 192.168.131.132. > 192.168.131.138.: Flags [S], seq , win , options [mss ,sackOK,TS val ecr ,nop,wscale ], length
::11.168343 IP 192.168.131.138. > 192.168.131.132.: Flags [S.], seq , ack , win , options [mss ,sackOK,TS val ecr ,nop,wscale ], length
::11.168377 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.168507 IP 192.168.131.132. > 192.168.131.138.: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP: GET /file_64KB HTTP/1.1
::11.168728 IP 192.168.131.138. > 192.168.131.132.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.168964 IP 192.168.131.138. > 192.168.131.132.: Flags [.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP: HTTP/1.1 OK
::11.168992 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.169150 IP 192.168.131.138. > 192.168.131.132.: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.169174 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.169176 IP 192.168.131.138. > 192.168.131.132.: Flags [.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.169180 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.169278 IP 192.168.131.138. > 192.168.131.132.: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.169294 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.169308 IP 192.168.131.138. > 192.168.131.132.: Flags [.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.169310 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.169375 IP 192.168.131.138. > 192.168.131.132.: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.169414 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.169713 IP 192.168.131.132. > 192.168.131.138.: Flags [F.], seq , ack , win , options [nop,nop,TS val ecr ], length
::11.170218 IP 192.168.131.138. > 192.168.131.132.: Flags [F.], seq , ack , win , options [nop,nop,TS val ecr ], length
::11.170243 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
背景知识:关于Flags后面紧跟的中括号里面的内容所表达的意思:
- S = SYN,表示发起连接标识
- P = PUSH,表示传送数据标识
- F = FIN,表示关闭连接标识
- . + ack 表示确认包
上面的结果显示了两次使用http协议下载文件的过程(从每一行的最后的字段都可以看出规律)。
包括三个过程:TCP连接建立--HTTP协议下载文件--TCP连接关闭。下面逐一分析这三个过程:
把客户端192.168.131.132记为A,服务端192.168.131.138记为B,则有
(1)TCP三次握手连接建立过程:
::11.163215 IP 192.168.131.132. > 192.168.131.138.: Flags [S], seq , win , options [mss ,sackOK,TS val ecr ,nop,wscale ], length
::11.163355 IP 192.168.131.138. > 192.168.131.132.: Flags [S.], seq , ack , win , options [mss ,sackOK,TS val ecr ,nop,wscale ], length
::11.163390 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
第一步:A向B发送连接请求[S],seq =
第二步:B向A发送同意连接[S.],ack = + 1 = 3124300131, seq =
第三次:A向B发送确认连接[.],这里是由于tcpdump采用了相对量的表示方法,ack = 1的意思是ack的值等于第二步中的 seq 值加上1,实际上是 + 1 =
(2)HTTP协议部分(先挖坑,后面学习完之后再来分析HTTP过程)
第一行:HTTP: GET /file_64KB HTTP/1.1
::11.163458 IP 192.168.131.132. > 192.168.131.138.: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP: GET /file_64KB HTTP/1.1
::11.163569 IP 192.168.131.138. > 192.168.131.132.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.163787 IP 192.168.131.138. > 192.168.131.132.: Flags [.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP: HTTP/1.1 OK
::11.163813 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.163848 IP 192.168.131.138. > 192.168.131.132.: Flags [.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.163862 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.163969 IP 192.168.131.138. > 192.168.131.132.: Flags [.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.163975 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.164011 IP 192.168.131.138. > 192.168.131.132.: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.164014 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.164038 IP 192.168.131.138. > 192.168.131.132.: Flags [.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.164043 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.164062 IP 192.168.131.138. > 192.168.131.132.: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.164065 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.164098 IP 192.168.131.138. > 192.168.131.132.: Flags [.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.164112 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.164149 IP 192.168.131.138. > 192.168.131.132.: Flags [.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.164154 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
::11.164180 IP 192.168.131.138. > 192.168.131.132.: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
(3)TCP连接释放过程
::11.164180 IP 192.168.131.138. > 192.168.131.132.: Flags [P.], seq :, ack , win , options [nop,nop,TS val ecr ], length : HTTP
::11.164183 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length ::11.164485 IP 192.168.131.132. > 192.168.131.138.: Flags [F.], seq , ack , win , options [nop,nop,TS val ecr ], length
::11.164863 IP 192.168.131.138. > 192.168.131.132.: Flags [F.], seq , ack , win , options [nop,nop,TS val ecr ], length
::11.164882 IP 192.168.131.132. > 192.168.131.138.: Flags [.], ack , win , options [nop,nop,TS val ecr ], length
第一步:A → B :seq = u = 152,
第二步:B → A :seq = w = ,ack = u + 1 = 153。
第三步:A → B :ack = w + 1 =
只有三步的原因是:在TCP释放连接过程的第一个过程之后,由于第二个过程和第三个过程之间,B没有数据发送给A,因此这里将两个过程一起发送给A。
计算机网络(1)- TCP的更多相关文章
- 计算机网络及TCP/IP知识点(全面,慢慢看)
TCP/IP网络知识点总结 一.总述 1.定义:计算机网络是一些互相连接的.自治的计算机的集合.因特网是网络的网络. 2.分类: 根据作用范围分类: 广域网 WAN (Wide Area Networ ...
- 计算机网络 之 TCP协议报文结构
前言:上学期实训课,由于要做一个网络通信的应用,期间遇到各种问题,让我深感计算机网络知识的薄弱.于是上网查找大量的资料,期间偶然发现了roc大神的博客,很喜欢他简明易懂的博文风格.本文受roc的< ...
- 计算机网络要点---TCP
计算机网络要点---TCP 浏览器在通过域名通过dns服务器找到你的服务器外网ip,将http请求发送到你的服务器,在tcp3次握手之后(http下面是tcp/ip),通过tcp协议开始传输数据,你的 ...
- 计算机网络(7)-----TCP协议概述
传输控制协议(Transmission Control Protocol) 概念 一种面向连接的.可靠的.基于字节流的传输层通信协议,由IETF的RFC 793定义.在简化的计算机网络OSI模型中,它 ...
- Day 6-1计算机网络基础&TCP/IP
按照功能不同,人们将互联网协议分为osi七层或tcp/ip五层或tcp/ip四层(我们只需要掌握tcp/ip五层协议即可) 每层运行常见物理设备: TCP/IP协议: Transmission Con ...
- 计算机网络知识—(TCP)
计算机网络在IT行业的重要性 IT即互联网技术,从事的工作和网络有很大的关系,前端要负责和后台(服务器)进行交互,其必然得经过网络,所以懂点网络知识有很大的帮助. 网络模型数据处理过程 传输层协议的作 ...
- 计算机网络:TCP协议建立连接的过程为什么是三次握手而不是两次?【对于网上的两种说法我的思考】
网上关于这个问题吵得很凶,但是仔细看过之后我更偏向认为两种说的是一样的. 首先我们来看看 TCP 协议的三次握手过程 如上图所示: 解释一下里面的英文: 里面起到作用的一些标志位就是TCP报文首部里的 ...
- 初探计算机网络之TCP/IP网络协议
网络协议 在计算机诞生以来,从最原始的单机模式到现在多台计算机协同工作,形成计算机网络,从前很难想象的信息共享.多机合作.大规模计算在今天也早已成了现实.在早期,计算机网络需要解决的痛点,就是怎样 ...
- 计算机网络(11)-----TCP连接的建立和释放
TCP连接的建立和释放 概述 TCP运输连接的建立和释放是每一次面向连接的通信中必不可少的过程,运输连接有三个阶段:连接建立,数据传送和连接释放. TCP连接的建立 如图所示,假定A主机是客户端程序, ...
- 计算机网络(10)-----TCP的拥塞控制
TCP的拥塞控制 拥塞(congestion) 在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏. 拥塞控制 拥塞控制就是防止过多的数据注入到网络中,这样可以使网 ...
随机推荐
- Android系统开发实务实训
实训项目 : Android系统开发实务实训 项目成品名称: 绝地坦克 ...
- FileDetail
import org.apache.hadoop.conf.*; import org.apache.hadoop.fs.*; import java.io.IOException; import j ...
- Hadoop点滴-Hadoop的IO
Hadoop自带一套原子操作用于数据的I/O操作. 如果系统中需要处理的数据量达到Hadoop的处理极限时,数据被损害的概率还是很高的 检测数据是否被损害的常见措施是,在数据第一次被引进系统时,计算校 ...
- SpringCloud Feign 之 超时重试次数探究
SpringCloud Feign 之 超时重试次数探究 上篇文章,我们对Feign的fallback有一个初步的体验,在这里我们回顾一下,Fallback主要是用来解决依赖的服务不可用或者调用服务失 ...
- poi下载excel模板
/** * 下载模板 * @param tplName * @param returnName * @param response * @param request * @throws Excepti ...
- 激突要塞代码解阵算法+用C++/Python处理代码
激突要塞的代码长度为6的倍数,其中每6个字符代表着一个单位,这六个字符中,第一位代表着单位的种类,后五位则包含着单位角度.X值.Y值的信息. 那么这个第一位究竟代表什么呢?一图以示之. 那么在代码中就 ...
- gitbook 入门教程之从零到壹发布自己的插件
什么是插件 Gitbook 插件是扩展 Gitbook 功能的最佳方式,如果 Gitbook 没有想要的功能或者说网络上也没有现成的解决方案时,那么只剩下自食其力这条道路,让我们一起来自力更生开发插件 ...
- springboot结合jpa
idea中新建springboot项目,引入spring-boot-starter-data-jpa依赖 application.yml中配置数据库连接,示例如下: spring: datasourc ...
- asp.net core learn
.NET Core WebApi RESTful规范 RESTful API 最佳实践 理解RESTful架构 接口版本控制 Support multiple versions of ASP.NET ...
- Redis开发与运维:数据迁移(下)
上一篇,有朋友留言redis-port,借此机会我尝试使用一下redis-port这个同步工具 redis-port 已编译版 https://github.com/CodisLabs/redis-p ...