1.1 网络通信概念
网络编程的目的
连接,信息交换
网络编程中两个主要问题
- 如何准确定位到网络上的一台或多台主机
- 找到主机后如何进行通信
网络编程的要素
地址
- ip_公网ip/内网ip
- 端口号
网络通信协议
javaweb:网页编程 B/S
网络编程 TCP/DCP
1.2 ip
ip地址:inetAddress
-
唯一定位一台网络上的计算机
-
127.0.0.1:本机localhost
-
ip地址的分类
1.3 端口
端口表示计算机上的一个程序的进程
-
不同的进程有不同的端口号,用以区分软件
-
每个协议端口有0-65535个
-
单个协议下,端口号不能冲突
-
端口分类
-
公有端口 0-1023
- http:80
- https:443
- FTP:21
- Telent:23
-
程序注册端口:1024-49151,分配用户或者程序
- Toncat:8080
- MySQL:3306
- Oracle:1521、
-
动态、私有:49152-65535
netstat -ano #dos命令:查看端口分配情况 Ctrl+Shift+Esc 打开任务管理器
-
1.4 通信协议
协议:约定俗称的一套标准
网络协议用到最广的一组协议:TCP/IP协议
TCP UCP 对比
TCP:打电话
-
连接,稳定
-
三次握手,四次挥手
1.连接 客:发送连接报文SYN 服:接受连接报文SYN,发送连接报文SYN+确认报文ACK 客:接受ACK报文,发送确认报文ACK,建立连接 服:接受ACK报文,建立连接 2.断开 客:发送断开报文FIN 服:接受断开报文FIN,发送确认报文ACK——可继续发送数据 服:发送断开报文FIN——发送完数据后 客:接受断开报文FIN,发送确认报文ACK,time_wait状态,等待2MSL-数据一个来回时间,确保服务端收到ACK 服:接受ACK,断开
-
客户端,服务端
-
传输完成,释放连接,效率低
UCP:发短信
- 不连接,不稳定
- 客户端与服务端,无明确的界限
- 不管有没有准备好,都可以发送
- 类似导弹攻击
- DDOS攻击:饱和攻击,单位时间发送大量请求,占用服务器端口资源,使其瘫痪
1.5 TCP三次握手四次挥手详解
三次握手
TCP三次握手是服务端与客户端建立稳定连接的开始
过程
服务端新建套接字,绑定ip与端口后开始进入监听状态
客户端新建套接字之后调用connect,主动向服务器发送连接请求SYN——同步序列编号,是TCP/IP建立连接时使用的握手信号
服务端接收到SYN请求之后,将连接放入内核等待队列中,并向客户端发送SYN + ACK——确认字符,表示发来的数据已确认接收无误
客户端接收到服务端的SYN+ACK报文后,向服务端发送确认报文ACK,进入连接状态
服务端收到客户端的确认报文ACK后,也进入连接状态
为什么握手是三次,而不是两次或者四次?
两次不安全,四次没必要
TCP通信需要确定双方都有数据收发的能力,得到ACK响应则认为对方具有数据收发的能力,因此双方都要发送SYN确保对方具有通信的能力。
第一次客户端向服务端发送SYN请求,表明客户端有数据发送能力;第二次服务端接收到SYN,向客户端发送ACK,表明服务端具有数据收发能力;第三次客户端接收到服务端ACK后,向服务端发送ACK,表明客户端有数据接收能力。所以握手最少三次,才能都确定双方都有数据接收能力
三次握手可以携带数据吗?
前两次不行,最后一次可以
因为前两次握手是确认双方,如果有人恶意攻击服务器,每次在第一次握手中SYN报文添加大量垃圾数据,重复发送,服务器需要花费大量内存空间来缓冲这些数据,服务器更容易被攻击
ISN代表什么?意义何在?ISN是固定不变的吗?ISN为何要动态随机
答:ISN全称是Initial Sequence Number,是TCP发送方的字节数据编号的原点,告诉对方我要开始发送数据的初始化序列号。
ISN如果是固定的,攻击者很容易猜出后序的确认号,为了安全起见,避免被第三方猜到从而发送伪造的RST报文,因此ISN是动态生成的
什么是半连接队列
服务器第一次接收到客户端的SYN请求后,进入半连接状态,因为双方还没有完全建立连接,服务器会把在这个状态下收到的请求放在一个队列中,这个队列就叫半连接队列
四次挥手
客户端主动调用close时,向服务端发送结束报文段FIN
服务端接收到FIN后,发送确认字段ACK,此时如果服务端有数据要发送的话,客户端依然需要接收
服务端发送数据完毕后,发送结束字段FIN
客户端接收到FIN后发送确认字段ACK,等待2MSL(防止服务端丢包重发FIN)后断开连接
服务端接收到ACK后,断开连接
为什么握手是三次,而挥手时需要四次呢?
其实在TCP握手的时候,接收端将SYN包和ACK确认包合并到一个包中发送的,所以减少了一次包的发送。而在挥手时,客户端发送FIN,但服务器有可能还有一些数据包没有发送完,故而将FIN包与ACK包分开发送,先发送确认字段ACK,数据全部传输完后,再发送结束字段FIN
TIME_WAIT状态有什么作用,为什么主动关闭方没有直接进入CLOSED状态释放资源?
答:如果主动关闭方进入CLOSED状态后,被动关闭方发送FIN包后没有得到ACK确认,超时后就会重传一个FIN包。如果客户端没有TIME_WAIT状态而直接进入CLOSED状态释放资源,下次启动新的客户端就可能使用了与之前客户端相同的地址信息,有两个危害,第一种是这个刚启动的新的客户端绑定地址成功时,就会收到了一个重传的FIN包,对新连接就会造成影响。第二种是如果该新客户端向相同的服务端发送SYN连接请求,但是此时服务端处于LAST_ACK状态,要求收到的是ACK而不是SYN,因此就会发送RST重新建立请求。
为什么TIME_WAIT状态需要经过2MSL才能进入CLOASE状态?
答:MSL指的是报文在网络中最大生存时间。在客户端发送对服务端的FIN确认包ACK后,这个ACK包有可能到达不了,服务器端如果接收不到ACK包就会重新发送FIN包。所以客户端发送ACK后需要留出2MSL时间(ACK到达服务器器+服务器发送FIN重传包,一来一回)等待确认服务器端缺失收到了ACK包。也就是说客户端如果等待2MSL时间也没收到服务器端重传的FIN包,则就可以确认服务器已经收到客户端发送的ACK包
一台主机上出现大量的TIME_WAIT是什么原因?应该如何处理?
答:TIME_WAIT是主动关闭方出现的,一台主机出现大量的TIME_WAIT证明这台主机上发起大量的主动关闭连接。常见于一些爬虫服务器。这时候我们应该调整TIME_WAIT的等待时间,或者开启套接字地址重用选项
一台主机上出现大量的CLOSE_WAIT是什么原因?应该如何处理?
答:CLOSE_WAIT是被动关闭方收到FIN请求进行回复之后的状态,等待上层程序进一步处理,若出现大量CLOSE_WAIT,有可能是被动关闭方主机程序中忘了最后一步断开连接后调用close释放资源。这是一个 BUG.,只需要加上对应的 close 即可解决问题
tcp连接管理中的保活机制
答:tcp通信中,若两端长时间没有数据往来,则这时候每隔一段时间,服务端会向客户端发送一个保活探测数据报,要求客户端进行回复。若连续多次没有收到响应,就认为连接已经断开。长时间默认为7200s,每隔一段时间默认为75s,连续多次无响应默认为9次。这些数据都可以在套接字中修改,接口:Setsockopt