目录
一、UDP
1、UDPAPI
2、UDPAPI的使用
二、TCP
1、TCPAPI
2、TCP的相关特性
2.1 确认应答
2.2 超时重传
2.3 连接管理(三次握手,四次挥手)
2.4 滑动窗口
2.5 流量控制
2.6 拥塞控制
2.7 延时应答
2.8 捎带应答
2.9 面向字节流
2.10 异常情况的处理
3、TCP和UDP的区别
通过计算机网络可以实现多台计算机的连接,但是不同计算机的操作系统和硬件体系不同,为了提供通信支持,位于同一个网络中的计算机在进行连接和通信时必须遵守一定的规则,在计算机网络中,这些连接和通信的规则称为网络通信协议。
网络通信协议有很多种,目前应用最广泛的是TCP/IP协议,和UDP协议。
在传输层的两个重要的高级协议分别是UDP和TCP,其中UDP是User Datagram Protocol的缩写,称为用户数据报协议;TCP是Transmission Contral Protocol的缩写,称为传输控制协议。
一、UDP
UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。当一台计算机向另一台计算机发送数据时,发送端不会确认接收端是否存在,就会发送数据,同样接收端在收到数据后,也不会向发送端反馈是否收到数据。
由于使用UDP消耗资源少,通信效率高,使用通常会使用到音频、视频和普通数据的传输,列如视频会议使用UDP,因为这种情况即使偶尔丢失几个数据包,也不会对接收结果产生太大影响。在使用UDP传输数据时,由于UDP的面向无连接,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP。
1、UDPAPI
UDP是一种无连接的协议,因此在通信时发送端和接收端不用建立连接。
UDP提供了DatagramPacket类和DatagramSocket类发送数据。
DatagramPacket类用于封装UDP通信中发送或者接收的数据。
使用DatagramSocket类的实例对象可以发送和接收DatagramPacket数据包。
方法声明 | 功能描述 |
void receive(DatagramPacket p) | 接收数据填充到DatagramPacket数据包中 |
void send(DatagramPacket p) | 发送DatagramPacket数据包 |
void close() | 关闭当前Socket |
2、UDPAPI的使用
接收端
public class ReceiverSocket {
public static void main(String[] args) throws IOException {
//创建一个数组,用于接收数据
byte[]array=new byte[1024];
//定义一个DatagramSocket对象,端口号为9090
DatagramSocket datagramSocket=new DatagramSocket(9090);
//定义一个DatagramPacket对象,用于接收数据
DatagramPacket dp=new DatagramPacket(array,array.length);
System.out.println("等待接收数据");
datagramSocket.receive(dp);
//接收得到的信息
String str=new String(dp.getData(),0,dp.getLength())+"from"+dp.getAddress().getHostAddress()+":"+dp.getPort();
System.out.println(str);
//释放资源
datagramSocket.close();
}
}
发送端
public class SenderSocket {
public static void main(String[] args) throws IOException {
//创建一个DatagramSocket对象
DatagramSocket ds=new DatagramSocket(3000);
//要发送的数据
String str="hello bit";
//将定义的字符串转化为字节数组
byte[]array=str.getBytes();
//创建DatagramPacket进行发送
DatagramPacket dp=new DatagramPacket(array,array.length, InetAddress.getByName("localhost"),9090);
System.out.println("发送信息");
ds.send(dp);
ds.close();
}
}
二、TCP
TCP是面向连接的通信协议,即在传输数据前先在发送端和接收端建立逻辑连接,然后在传输数据。在TCP连接中必须要明确客户端和服务器端,由客户端向服务器端发出连接请求,每次连接的创建都需要经过“三次握手”。第一次握手,客户端向服务器端发出连接请求,等待服务器确认;第二次握手,服务器端向客户端回应一个响应,通知客户端收到了连接请求;第三次握手,客户端再次向服务器端发送确认信息,确认连接。
由于TCP的面向连接特性,它可以保证传输数据的安全性,是一个被广泛采用的协议。例如,在下载文件时,如果数据接收不完整,将会导致文件数据缺失而不能被打开,因此,下载文件时必须采用TCP。
1、TCPAPI
TCP通信要严格区分客户端和服务器端,在通信时,必须先由客户端去连接服务器端才能实现通信,服务器端不能主动连接客户端,并且服务器端程序需要提前启动,等待客户端的连接。
Java提供了两个实现TCP程序的类,一个是ServerSocket类,用于表示服务器端,另一个是Socket类,用于表示客户端。通信时,首先要创建代表服务器端的ServerSocket对象,创建该对象相当于开启了一个服务,此服务会等待客户端的连接;然后创建代表客户端的Socket对象,使用该对象向服务器端发起连接请求,服务器端响应请求后,两者才建立连接,开始通信。
2、TCP的相关特性
2.1 确认应答
实现TCP可靠传输的核心机制就是确认应答(ack),发送方将数据发送给接收方,接收方将应答报文发送给发送方,发送方收到应答报文后就知道数据传输成功了。
在网络传输的过程中会出现“后发先到”的情况,TCP要完成两个工作:
1、确保应答报文和发送出去的数据能对上号,不要出现歧义;
2、确保在出现后发先至的现象时,能够让应用程序按照正确的顺序来理解数据;
2.2 超时重传
如果在网络传输的过程中,出现了丢包,发送方就收不到ack,使用超时重传,对确认应答进行补充。
重传操作大幅度的提升了数据能够被传过去的概率,重传就是一个很好的丢包补救措施,会等待一段时间,超过这个时间就会重传,每经历一次超时,等待时间就会变长,时间长到一定程度,就会让TCP重置。
如果是ack包丢了,又重传了一次,TCP有“接收缓冲区”保存了已经接收了的数据和数据的序号,再发一次,如果是重复的,接收方把后来的数据丢掉,确保在read的时候,读到的是只有一条数据。
2.3 连接管理(三次握手,四次挥手)
连接管理就是建立连接和断开连接
建立连接(三次握手)
TCP中的握手,只是给对方传输一个简短的,没有业务的数据包,唤起对方的注意,触发后续的操作。TCP的三次握手,是指TCP在建立连接的过程中,需要通信双方一共“打三次招呼”才会完成建立连接。
三次握手要解决什么问题?四次握手,两次握手可行?
三次握手的核心作用:
1、确认当前网络是否通畅,可以传输;
2、让发送方和接收方都能确认自己的发送能力和接收能力均正常;
3、让通信双方,在握手的过程中,针对一些重要的参数,进行协商;
四次握手:可以,但没有必要,影响效率;
两次握手:不可以,无法同步信息,完成验证的效果;
断开连接(四次挥手)
建立连接,一般都是客户端发起的,断开连接,客户端和服务器都可以发起。
此处的四次挥手,能否把中间两次合二为一?
不一定
不能合并的原因:
ack和第二次FIN的触发时机是不同的,ack是内核响应的,服务器端收到FIN会立刻返回ack,第二个FIN是应用程序触发的,服务器端使用close()方法才会触发FIN。
三次握手中,ack和第二个syn是内核触发的,同一时机,可以合并,四次挥手,ack是内核触发的,第二个FIN是应用程序触发的,时机不同,不能合并。
2.4 滑动窗口
滑动窗口可以提高效率,TCP的可靠传输是影响效率的,滑动窗口,就可以让可靠传输的性能影响更小一点,缩短和UDP的差距。
批量传输,也不是:“无限”的,达到上限后,再统一等待ack,不等待的情况下,批量发最多的数据量,称为“窗口大小”。
2.5 流量控制
滑动窗口越大越好吗?
如果传输的速度太快,就可能使接收方处理不过来,此时,接收方就会出现丢包的现象,发送方还得重传。
流量控制:站在接收方的角度,反向制约发送方的传输速率,发送方的发送速率,不应该超过接收方的处理能力。
如何衡量处理能力?
直接通过接收方缓冲区的剩余空间大小,作为衡量处理能力的指标。
2.6 拥塞控制
拥塞控制,不仅仅考虑接收方的处理能力,还有整个通信路径。
由于中间节点,结果更复杂,无法量化,因此,就通过“实验”的方法,来找到合适的值。
先让发送方以比较低的速度发送数据,顺利不丢包,再使用更大的窗口,更快的速度,不断增大,出现问题,再调整。
2.7 延时应答
延时应答,本质是为了提高传输效率。
延时返回ack,给接收方更多的时间,来读取接收缓冲区的数据。此时,接收方读了这个数据之后,缓冲区剩余的空间变大了,返回的窗口大小也就更大了。
2.8 捎带应答
在延时应答的基础上,进一步提高效率,网络通信中,往往是“一问一答”的通信类型。
在通信过程中,ack是立刻返回的,response是应用程序代码返回的,二者的时机是不同的。由于,TCP引入了延时应答,ack等待一会,response计算好了,response返回带上ack。
2.9 面向字节流
TCP传输是面向字节流的,面向字节流可能会产生粘包问题。
如何解决粘包问题?
核心思路:通过定义好应用层协议,明确应用层数据包之间的边界。1、引入分隔符
2、引入长度
2.10 异常情况的处理
异常情况:
1、进程崩溃;2、主机关机(正常流程);
3、主机掉电(非正常流程);
4、网线断开;
1、进程崩溃
进程结束,异常终止了,文件描述符也就释放了,相当于调用了socket.close(),此时,就会触发FIN,对方收到了之后,自然就会返回FIN和ack,然后再进行ack传输。
2、主机关机
在进行关机的时候,就会触发强制终止进程的操作,触发FIN,对方收到就会返回ack和FIN,系统关闭之前,对端返回ack和FIN到了,就可以进行正常的四次挥手,如果ack和FIN没到,无法进行后续的ack响应,重传无响应,放弃连接。
3、主机掉电和网线断开
主机掉电和网线断开类似,都是一瞬间,来不及关闭进程,来不及发送FIN。
(1)、如果是接收方断电或者断网,发送方发送数据就会一直等待ack,触发超时重传,触发TCP连接重置功能,发送“复位报文段”。
(2)、如果是发送方断电或者断网,TCP中提供了“心跳包”机制,接收方周期性的给发送方发送一个特殊,不带业务的数据包,如果对方多次没有应答,视为对方已经断开连接。
3、TCP和UDP的区别
1、TCP是有连接的,UDP是无连接的。
2、TCP是可靠传输的,UDP是不可靠传输的。
3、TCP是面向字节流的,UDP是面向数据报的。
4、TCP和UDP都是全双工的。