深度解析TCP/IP

  • 1 应用层
  • 2 传输层
    • 2.1 端口号
    • 2.2 UDP协议
      • 2.2.1 UDP的特点
      • 2.2.2 面向数据报
      • 2.2.3 UDP缓冲区
      • 2.2.4 UDP注意事项
      • 2.2.5 基于UDP的应用层协议
    • 3 TCP协议
      • 2.3.1 TCP1大核心和8大特性
        • 特性1:==确认应答(核心机制)==
        • 特性2:超时重传
        • 特性3:连接管理
        • 特性4:滑动窗口
        • 特性五:流量控制
        • 特性六:拥塞控制
        • 特性七:延迟应答
        • 特性八:捎带应答
      • 2.3.2 粘包问题
      • 2.3.3 TCP异常情况
      • 2.3.4 基于TCP应用层协议
      • 2.3.5 小结TCP
    • 2.4TCP/UDP对比
  • 3 网络层
    • 3.1 IP协议
      • 3.1.1 头格式
      • 3.1.2 网络划分
      • 3.1.3 私网IP地址
      • 3.1.4 路由
  • 4 数据链路层
    • 4.1 以太网
      • 4.1.1 以太网帧格式
    • 4.2 MAC地址和IP地址
    • 4.3 MTU
    • 4.4 ARP协议
  • 5 物理层
  • 6 补充重点
    • 6.1 DNS
    • 6.2 浏览器中输入url后, 发生的事情
    • 6.3 NAT技术

1 应用层

针对特定应用的协议

简单的说就是咱们的程序这一层 (SSH、SFTP、HTTP、DNS解析域名),是为了实现程序去用的

2 传输层

2.1 端口号

端口号作用:找到应用程序

(1)知名端口号:知名程序在启动之后占用的端口号(0-1023)

  • SSH服务器, 使用22端口
  • FTP服务器, 使用21端口
  • TELNET服务器, 使用23端口
  • HTTP服务器, 使用80端口
  • HTTPS服务器, 使用443

(2)动态端口号:1024-65535 最大端口号

两个程序不能使用同一个端口号,一个程序可以使用两个端口号
(理解:程序 – >人 ;端口号 --> 手机号)

2.2 UDP协议

16位源端口号:源程序的端口号,根据这个端口号可以定位到发送端程序
16位目标端口号:目标端口号,定位接收端的应用程序

16位UDP长度 = UDP头部长度 + 数据长度
16位效验和:效验数据的正确性

效验和的执行逻辑:
假设效验和的算法是MD5,MD5(UDP头部信息+UDP数据)
发送端就会将UDO所有内容发送给接收端,此时接收端就有了UDP的效验和所有数据,接收端就可以根据MD5(UDP头部信息+UDP数据),得到一个正确的效验和,然后用这个正确的效验和UDP头部信息中的效验进行对比,如果相等则表示数据是正确的,否则数据就是错误的,直接舍弃。

2.2.1 UDP的特点

  • 无连接: 知道对端的IP和端口号就直接进行传输, 不需要建立连接
  • 不可靠: 没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP协议层也不 会给应用层返回任何错误信息
  • 面向数据报: 不能够灵活的控制读写数据的次数和数量

2.2.2 面向数据报

应用层交给UDP多长的报文, UDP原样发送, 既不会拆分, 也不会合并

用UDP传输100个字节的数据:
如果发送端调用一次sendto, 发送100个字节, 那么接收端也必须调用对应的一次recvfrom, 接
收100个字节; 而不能循环调用10次recvfrom, 每次接收10个字节;

2.2.3 UDP缓冲区

UDP只有接收缓冲区,并没有发送缓冲区

  • UDP必须要有接收缓冲区,可以大大提高UDP的工作效率
  • UDP之所以不需要要发送缓冲区,是因为UDP是不需要连接的,也就是不需要等待对方先连接的,所以最快的佛南工作方式就是拿到消息就发

TCP和UDP都是全双工的

  • 全双工:发送端或者接收端既可以发送消息,又可以接收消息
  • 半双工:发送端只能发送消息,不能接收消息

2.2.4 UDP注意事项

因为UDP头部中有一个16位的长度(数据+头部),因此一个UDP的最大包必须是16位可以表示的。

所以UDP理论可以传输的大小为64K

如果UDP编程的数据包大于64K的解决方案

  1. 在应用层进行数据包的拆分和组合(程序员定义)
  2. 不进行手动处理,交给TCP/IP协议去处理,他会在网络层进行分包和组包

实际工作中,会采取第一种(应用层组包和分包来实现UDP大数据的传递),因为如果使用了第二种方式,那么任意一个包丢失之后,那么整个数据包也丢失了,风险极大(网络环境非常复杂),因此不会选用第二种方式。

2.2.5 基于UDP的应用层协议

  • NFS: 网络文件系统
  • TFTP: 简单文件传输协议
  • DHCP: 动态主机配置协议
  • BOOTP: 启动协议(用于无盘设备启动)
  • DNS: 域名解析协议

3 TCP协议

  • 源/目的端口号: 表示数据是从哪个进程来, 到哪个进程去
  • 32位序号/32位确认号
  • 4位TCP报头长度: 表示该TCP头部有多少个32位bit(有多少个4字节); 所以TCP头部最大长度是15 * 4= 60
  • 6位标志位
    URG:表示紧急消息
    ACK:确认应答表示
    PSH:用来表示让接收端将消息从缓冲区取走
    RST:复位标识符
    SYN:同步标识符。TCP初次连接
    FIN:结束表示。TCP断开连接
  • 16位窗口大小:它记录的是接收缓冲区窗口的大小,这个是动态改变的
    (不等于滑动窗口的大小,因为滑动窗口的大小是固定不变的,所以不需要传)
  • 16位校验和: 用来确定当前数据是否是正确的
  • 16位紧急指针: 标识哪部分数据是紧急数据;
  • 40字节头部选项: 暂时忽略

2.3.1 TCP1大核心和8大特性

特性1:确认应答(核心机制)

保障TCP稳定的核心机制

每一个ACK都带有对应的确认序列号, 意思是告诉发送者, 我已经收到了哪些数据; 下一次你从哪里开始发

特性2:超时重传

为解决确认应答的非正常情况
对于发送重复消息的问题,不用担心,因为系统(内核)帮程序去做去重操作

TCP稳定的核心就是:确认应答+超时重传

超时重发策略1:使用递增时间段来发送

超时重发策略2:尝试多次发送失败后停止发送
当进经过了一定次数的发送后,还是没有结果,那么发送端就会认为接收端下线了

特性3:连接管理

连接:3次握手
断开连接:4次挥手

3次握手:
TCP特性:有连接
有连接必须要证明4个:

  1. 发送方的发送能力(话筒)
  2. 发送方的接收能力(耳机)
  3. 接收方的发送能力(对方话筒)
  4. 接收方的接收能力(对方的耳机)

4次挥手:

TCP有发送缓冲区和接收缓冲区,所以

  • 如果缓冲区里有数据,就得把数据处理完走
  • 若没有缓冲区没有数据,直接就走

3次挥手行不行?
有可能可以,23步有可能会合并(如果接收端没有要处理东西的话)

CLOSE_WAIT -> 如果发现服务器端存在大量的CLOSE_WAIT说明程序有什么问题?
程序有BUG,程序中没有调用close()主导那个关闭连接

TIME_WAIT -> CLOSE 要经历两个MSL(最大生存时间)?

2MSL = ACK最大超时连接(1MSL) + 对方发给他消息的一个最大等待时间(1MSL)

(1)等ACK
(2)失败后,再发一个消息,再等重发的FIN

特性4:滑动窗口

目的:保证传输的性能

情况一:数据包已经抵达, ACK被丢了

当返回ack=6001说明服务器已经接收到了1-6000的数据了
ack返回的是接收缓冲区的最大值

如果最前面和最后面的丢了,那么服务器就会再发一遍,然后进行对比

情况二: 数据包就直接丢了

快速重传:
当前面的数据被正常补齐之后,返回ACK是最大值,这种机制叫作快重传

特性五:流量控制

接收端处理数据的速度是有限的. 如果发送端发的太快, 导致接收端的缓冲区被打满, 这个时候如果发送端继续发送, 就会造成丢包, 继而引起丢包重传等等一系列连锁反应

根据接收端的处理能力, 来决定发送端的发送速度. 这个机制就叫做流量控制

如果TCP协议头的16位窗口的大小位0,表示接收缓冲区已经满了,不能再发了。此时发送端就不会进行消息的发送了,发送端会定时发送一个探测包,用来检测接收缓冲区的大小,如果接收缓冲区有值了,那么消息就可以继续发送了

总结:以结果(接收缓冲区的大小)为导向进行数据的传递

特性六:拥塞控制

和你当前的网络有关

以当前时间的网络来动态调整收发的频率就叫拥塞控制

规则:
发包从1开始,以默认值16为临界值,当小于此值的时候,以指数增加的方式发包,当等于这个此值就有线性增长的方式发包,一直到有大量丢包的请求(发包已经到当前时间段的极致);这个时候就会:
(1)将发包值置为1
(2)再将临界值设置为最大发包值的一半
继续重复此过程,一直循环此过程
整个过程就叫慢开始

  • 当TCP开始启动的时候, 慢启动阈值等于窗口最大值;
  • 在每次超时重发的时候, 慢启动阈值会变成原来的一半, 同时拥塞窗口置回1;

总结:以当前网络环境的拥塞程度为导向

特性七:延迟应答

延迟应答是在流量控制的基础上进行优化发送效率

TCP:
策略一:固定一定时间段,发送一个延迟应答包
策略二:接收一定次数的包之后,来一个延迟应答

注意事项:延迟应答时间不能超过MSL(最大生存时间)
如果超过MSL就会触发超时重传,它会以为消息丢失

特性八:捎带应答

是在延迟应答的基础上继续又转换传输效率

在延迟应答的基础上, 我们发现, 很多情况下, 客户端服务器在应用层也是 “一发一收” 的. 意味着客户端给
服务器说了 “How are you”, 服务器也会给客户端回一个 “Fine, thank you”;
那么这个时候ACK就可以搭顺风车, 和服务器回应的 “Fine, thank you” 一起回给客户端

捎带应答是针对延迟应答所进行的性能优化

2.3.2 粘包问题

  1. 首先要明确, 粘包问题中的 “包” , 是指的应用层的数据包.
  2. 在TCP的协议头中, 没有如同UDP一样的 “报文长度” 这样的字段, 但是有一个序号这样的字段.
  3. 站在传输层的角度, TCP是一个一个报文过来的. 按照序号排好序放在缓冲区中.
  4. 站在应用层的角度, 看到的只是一串连续的字节数据.
  5. 那么应用程序看到了这么一连串的字节数据, 就不知道从哪个部分开始到哪个部分, 是一个完 整的应用层数据包

那么如何避免粘包问题呢?

归根结底就是一句话, 明确两个包之间的边界

  • 对于定长的包, 保证每次都按固定大小读取即可; 例如上面的Request结构, 是固定大小的, 那
    么就从缓冲区从头开始按sizeof(Request)依次读取即可;
  • 对于变长的包, 可以在包头的位置, 约定一个包总长度的字段, 从而就知道了包的结束位置;
  • 对于变长的包, 还可以在包和包之间使用明确的分隔符(应用层协议, 是程序猿自己来定的, 只 要保证分隔符不和正文冲突即可);

具体方法

  1. 使用/n作为流的结束符,这样流就有边界了,就能正常收发消息了
  2. 每次发固定大小的流信息,这样也能确定每个数据流的边界,也就能正常的收发消息了

对于UDP协议来说, 是否也存在 “粘包问题” 呢?

  • 对于UDP, 如果还没有上层交付数据, UDP的报文长度仍然在. 同时, UDP是一个一个把数据交 付给应用层. 就有很明确的数据边界.

  • 站在应用层的站在应用层的角度, 使用UDP的时候, 要么收到完整的UDP报文, 要么不收. 不会 出现"半个"的情况

2.3.3 TCP异常情况

  • 进程终止: 进程终止会释放文件描述符, 仍然可以发送FIN. 和正常关闭没有什么区别.
  • 机器重启: 和进程终止的情况相同.
  • 机器掉电/网线断开: 接收端认为连接还在, 一旦接收端有写入操作, 接收端发现连接已经不在了, 就会进行 reset. 即使没有写入操作,TCP自己也内置了一个保活定时器, 会定期询问对方是否还在. 如果对方不在, 也会把连接释放.
  • 另外, 应用层的某些协议, 也有一些这样的检测机制. 例如HTTP长连接中, 也会定期检测对方的状态. 例如 QQ, 在QQ断线之后,也会定期尝试重新连接

2.3.4 基于TCP应用层协议

  • HTTP:简单的请求-响应协议
  • HTTPS:以安全为目标的 HTTP 通道
  • SSH:安全外壳协议
  • Telnet:Internet远程登录服务的标准协议
  • FTP:文件传输协议
  • SMTP:电子邮件传输的协议

2.3.5 小结TCP

可靠性:

  • 校验和
  • 序列号(按序到达)
  • 确认应答
  • 超时重发
  • 连接管理
  • 流量控制
  • 拥塞控制

提高性能:

  • 滑动窗口
  • 快速重传
  • 延迟应答
  • 捎带应答

其他:

  • 定时器(超时重传定时器, 保活定时器, TIME_WAIT定时器等)

2.4TCP/UDP对比

  1. UDP是无连接的;TCP是有连接的
  2. UDP是不稳定的;TCP是稳定的
  3. UDP是面向数据报的;TCP是面向数据流的
  4. UDP没有发送缓冲区;TCP有发送缓冲区
  5. UDP是以高效性著称;TCP是以稳定性著称
  6. 使用的场景不同
    如果对稳定性要求比较高,那么应该使用TCP
    如果对消息丢失不敏感,要求性能比较高,那么可以考虑使用UDP

如何使用UDP实现稳定的消息传输?

参考TCP实现稳定性的特性来设计UDP

  • 确认应答
  • 超时重发
  • 连接管理
  • 流量控制
  • 拥塞控制

3 网络层

3.1 IP协议

3.1.1 头格式

  • 4位版本号(version): 指定IP协议的版本, 对于IPv4来说, 就是4
  • 4位头部长度(header length): IP头部的长度是多少个32bit, 也就是 length * 4 的字节数. 4bit表示最大的数字是15, 因此IP头部最大长度是60字节
  • 8位服务类型:3位优先权字段(已经弃用), 4位TOS字段, 和1位保留字段(必须置为0). 4位TOS分别表示: 最小延时, 最大吞吐量, 最高可靠性, 最小成本. 这四者相互冲突, 只能选择一个. 对于ssh/telnet这样的应用程序, 最小延时比较重要; 对于ftp这样的程序, 最大吞吐量比较重要
  • 16位总长度(total length): IP数据报整体占多少个字节
  • 3位标志字段: 第一位保留,第二位置为1表示禁止分片,第三位表示"更多分片"
  • 13位分片偏移:确定组包时的顺序
  • 8位生存时间SSL:一般为64,每经过路由器的跳转这个值-1,直到这个值等于0,表示是个无效的地址,直接舍弃。
  • 16位头部校验和:验证首部是否正确
  • 32位源地址和32位目标地址: 表示发送端和接收端

3.1.2 网络划分

IP地址分为两个部分, 网络号和主机号

网络号: 保证相互连接的两个网段具有不同的标识;
主机号: 同一网段内, 主机之间具有相同的网络号, 但是必须有不同的主机号;

A类 0.0.0.0到127.255.255.255
B类 128.0.0.0到191.255.255.255
C类 192.0.0.0到223.255.255.255
D类 224.0.0.0到239.255.255.255
E类 240.0.0.0到247.255.255.255

网络号:IP地址和子网掩码按位与

例子1:
子网掩码最后一位为0,到255有 255个
子网号最后一位从0,到0+255 = 255

例子2:
子网掩码最后一位为240,到255有 15 个
子网号最后一位从64,到64+15 = 79

3.1.3 私网IP地址

如果一个组织内部组建局域网,IP地址只用于局域网内的通信,而不直接连到Internet上,理论上 使用任意
的IP地址都可以,但是RFC 1918规定了用于组建局域网的私有IP地址

  • 10.*,前8位是网络号,共16,777,216个地址
  • 172.16.到172.31.,前12位是网络号,共1,048,576个地址
  • 192.168.*,前16位是网络号,共65,536个地址
    包含在这个范围中的, 都成为私有IP, 其余的则称为全局IP(或公网IP);

3.1.4 路由

过程:

  1. 当IP数据包, 到达路由器时, 路由器会先查看目的IP;
  2. 路由器决定这个数据包是能直接发送给目标主机, 还是需要发送给下一个路由器;
  3. 依次反复, 一直到达目标IP地址;

4 数据链路层

4.1 以太网

“以太网” 不是一种具体的网络, 而是一种技术标准; 既包含了数据链路层的内容, 也包含了一些
物理层的内容. 例如: 规定了网络拓扑结构, 访问控制方式, 传输速率等;

4.1.1 以太网帧格式

  • 源地址和目的地址是指网卡的硬件地址(也叫MAC地址), 长度是48位,是在网卡出厂时固化的;
  • 帧协议类型字段有三种值,分别对应IP、ARP、RARP;
  • 帧末尾是CRC校验码:用来效验数据的正确性

4.2 MAC地址和IP地址

  • IP地址描述的是路途总体的 起点 和 终点;
  • MAC地址描述的是路途上的每一个区间的起点和终点

4.3 MTU

大传输单元,MTU相当于发快递时对包裹尺寸的限制. 这个限制是不同的数据链路对应的物理层, 产生的限制

MTU 对 UDP 的影响

1500 - UDP(固定头部信息)8字节 - IP协议头部20字节 = 1472 字节

MTU对于TCP协议的影响

TCP的一个数据报也不能无限大, 还是受制于MTU. TCP的单个数据报的最大消息长度, 称为
MSS(Max Segment Size);
TCP在建立连接的过程中, 通信双方会进行MSS协商。

MTU = IP Header + TCP Header + DAT(MSS)

4.4 ARP协议

定义

ARP不是一个单纯的数据链路层的协议, 而是一个介于数据链路层和网络层之间的协议

作用:

ARP协议建立了主机 IP地址 和 MAC地址 的映射关系

工作方式:

  1. 源主机发出ARP请求在网络中寻找IP地址
  2. 目的主机收到请求并返回ARP应答数据包给源主机
  3. 此时源地址和目标地址已经找到,构建完成MAC地址,相应的以太帧也完成

5 物理层

以0,1代表电压的高低,灯光的闪灭,界定连接器和网络的规格

相当于一些基站,电信号和光信号

6 补充重点

6.1 DNS

TCP/IP中使用IP地址和端口号来确定网络上的一台主机的一个程序. 但是IP地址不方便记忆.

端口号:53

于是人们发明了一种叫主机名的东西, 是一个字符串, 并且使用hosts文件来描述主机名和IP地址的关系.

6.2 浏览器中输入url后, 发生的事情

  1. 浏览器会先检查你的url地址的正确性
  2. 浏览器会检查这个url有没有缓存,如果有缓存就取缓存
  3. DNS域名解析,拿到IP进行访问
  4. TCP 3次握手(TCP握手的内容传递和状态变化)
  5. HTTP 协议 Resquest 内容发送 (首行,head,空行,body)
  6. 服务器接收到请求,并且进行相应的业务处理
  7. 服务器端将结果返回给客户端
  8. 浏览器拿到返回的结果并调用浏览器的内核,实现前端页面的渲染
  9. TCP 的4次挥手

6.3 NAT技术

目的:解决 IP 不足的问题

本质:实现一个映射,内网 IP 到外网 IP 的映射

NAT缺点:

  1. 部署和运行 NAT 服务是需要硬件支持的
  2. 当 NAT 挂掉之后,整个局域网就瘫痪了

NAT vs 代理

  1. 应用场景:NAT 是解决 IP 不足的问题;代理是解决网络不能到达的问题
  2. 部署:NAT 通常会部署在防火墙;代理是一个软件,直接安装使用
  3. 所在层级:NAT 是网络层的;代理是应用层。

深度解析TCP/IP---网络原理的重重之重相关推荐

  1. 计算机tcpip网络原理与应用,清华大学出版社-图书详情-《TCP/IP网络编程原理与技术》...

    前言 随着Internet的发展,网络技术已经渗透到人们的生活和工作中.TCP/IP已经成为最流行的网络协议,且还在演变以满足未来的需要.在速度越来越快的计算机硬件和不断更新的软件发展的背后,TCP/ ...

  2. 【技术分享篇】从网卡到tcpip协议栈,再到应用程序丨tcp/ip网络编程丨网络api的实现原理丨sk_buff的作用

     从网卡 聊到tcp/ip协议栈,再到应用程序 1. posix tcp/ip网络编程 2. 网络api的实现原理 3. sk_buff的作用 [技术分享篇]面试中从网卡 聊到tcpip协议栈,再到应 ...

  3. 【网络通信与信息安全】之深入解析TCP/IP协议的实现和原理

    一.计算机网络体系结构分层 计算机网络体系结构分层示例图: 计算机网络体系结构说明: 不难看出,TCP/IP 与 OSI 在分层模块上稍有区别.OSI 参考模型注重"通信协议必要的功能是什么 ...

  4. 高等学校计算机科学与技术教材:tcp/ip网络编程技术基础,TCP/IP网络编程技术基础...

    TCP/IP网络编程技术基础 语音 编辑 锁定 讨论 上传视频 <TCP/IP网络编程技术基础>是2012年北京交通大学出版社出版的图书,作者是王雷. 书    名 TCP/IP网络编程技 ...

  5. TCP/IP网络协议栈面试经典题目

    目录 面试官:看你简历说精通TCP和IP,那我们来讨论下网络模型和TCP.IP协议,讲下你的理解先 面试官:看你画的图,TCP有自己的首部结构,这都有哪些字段,最好说说它们的作用 面试官:那TCP和U ...

  6. TCP/IP网络协议栈:IP协议

    <TCP/IP网络协议栈:以太网数据包结构.802.3> <TCP/IP网络协议栈:ARP协议详解> <TCP / IP攻击:ARP缓存中毒的基本原理.TCP序列号预测和 ...

  7. TCP/IP网络编程(3)

    基于DUP的服务端与客户端 在TCP/IP网络编程(2)中,介绍了TCP/IP的四层模型,传输层分为TCP和UDP两种方式,通过TCP套接字完成数据交换已经进行了介绍,下面介绍通过UDP套接字完成数据 ...

  8. TCP/IP网络编程(1)

    1. 套接字 套接字是由操作系统提供的网络数据通信软件设备,即使对网络数据传输原理不了解,也能够使用套接字完成网络数据传输.为了与远程计算机进行数据传输,需要连接到英特网,套接字就是进行网络连接的工具 ...

  9. TCP/IP网络编程 - 基础学习

    1. 创建Socket #include<sys/types.h> #include<sys/socket.h>int sock = ::socket(PF_INET, SOC ...

  10. TCP/IP网络初识

    TCP/IP网络初识 TCP/IP网络 测试实验环境(基础知识) 实验一,查看网卡(NIC)的MAC地址 实验 二:查看计算机的 IP 地址 实验三:DHCP服务器的作用 实验四:路由器 实验五:查看 ...

最新文章

  1. 深度解析2019中国机器人行业年会主旨报告:把脉中国机器人发展,助力产业创新与协作共融...
  2. Oracle Exadata 一体机关机过程(虚拟机环境)
  3. 笑傲江湖ol更新服务器正在维护,笑傲江湖ol4月22日更新内容 调整死亡复活设置...
  4. Java项目开发全程实录pdf
  5. springboot 添加 jsp支持
  6. Oulipo (KMP出现次数)
  7. jframe运行和预览大小不一样_在泉州楼市中12个热门置业板块中,购房竞争压力大小各不一样...
  8. iTextSharp 添加表格
  9. ​新手到底如何入门PLC?
  10. (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  11. Modeling Conversation Structure and Temporal Dynamics for Jointly Predicting Rumor Stance and Veraci
  12. pyecharts之参透神剧人物关系
  13. KMP --算法竞赛(33)
  14. GitHub下载 无法分配请求的地址_Hexo+Github--搭建个人博客(一)准备工作amp;amp;环境搭建
  15. ffmpeg 分离视频音频流 缺失sei信息
  16. 计算机图形杂志,计算机图形学顶级杂志、会议、期刊
  17. Redis-入门学习笔记
  18. 关于5944空间的所谓免费
  19. 关于下拉刷新你是否真的非常理解还是只会搬砖?附 Android 实例子源代码文件下载地址380个合集...
  20. LDA-线性判别分析(一)预备知识

热门文章

  1. 用php照片艺术化,不满足简单修图?这些应用能让照片充满艺术感
  2. 视屏剪辑软件(Pr)Premiere Pro CC 2018安装教程:
  3. 联想 M7400 pro Linux下 CUPS 驱动安装
  4. PyCharm安装LabelImg
  5. 企业微信API使用基本教程
  6. 基于BC95之AT命令的学习
  7. java sql 格式化_IDEA 格式化SQL代码技巧分享
  8. 基于 Python 与 mxget 的音乐下载器
  9. MySQL经典书籍推荐
  10. Javascript必须掌握的js库