概述:
两者都是通信协议, TCP、UDP 是传输层协议,但他们的通信机制与应用场景不同,下面来阐述两者的区别以及它们的应用场景。
TCP 与 UDP:
TCP(Transmission Control Protocol),又叫传输控制协议,UDP(User Datagram Protocol),又叫用户数据报协议,它们都是传输层的协议,但两者的机制不同,它们的区别如下:
特点 | TCP | UDP |
---|---|---|
连接性 | 面向连接 | 面向非连接 |
可靠性 | 可靠 | 不可靠 |
传输效率 | 慢 | 快 |
TCP/UDP编程模型:
从程序实现的角度来看,可以用下图来进行描述。
TCP:
从如上表格看到,TCP 是面向连接的,并且是一种可靠的协议,在基于 TCP 进行通信时,通信双方需要先建立一个 TCP 连接,建立连接需要经过三次握手,握手成功才可以进行通信,关于 TCP 三次握手、四次挥手的过程请看该文章。
另外 TCP 协议是一种可靠的传输协议,那么它是如何保证可靠性的呢?
UDP:
UDP 是一种面向无连接,且不可靠的协议,在通信过程中,它并不像 TCP 那样需要先建立一个连接,只要(目的地址,端口号,源地址,端口号)确定了,就可以直接发送信息报文,并且不需要确保服务端一定能收到或收到完整的数据。它仅仅提供了校验和机制来保障一个报文是否完整,若校验失败,则直接丢弃报文,不做任何处理。
可靠性:
在讲解 TCP 如何保证可靠性前,首先得理解什么是可靠。在通信的角度来看,可靠即要确保通信双方的通信信息不会丢失,若丢失了保证能够对其进行恢复,并且收到的信息内容与原发送内容一样。
在 TCP 中,传输报文都是通过建立的虚拟连接来进行传输,发送端传输的每一个 TCP 报文,都会对其进行编号(编号是由于网络传输的原因,发送的报文可能会乱序到达,因此需要根据编号对报文进行重排),并且开启一个计时器;当接收端收到报文后,并且通过校验和对收到的报文数据进行校验,若校验成功则会返回一个确认报文,告知发送端我已经成功收到该报文了;若发送端在计时器结束前仍未收到确认报文,则认为接收端接收失败,则会重传该报文;服务端若收到重复报文(根据编号发现已经是收到了),则会将该报文丢弃。
因此,从上面的机制可以知道,TCP 是通过重传、确认和校验和的方式来确保可靠。
注:校验和并不能检验数据是否被篡改过,想要保证数据的完整性可以了解一下数字签名
TCP 与 UDP 的应用场景:
从特点上我们已经知道,TCP 是可靠的但传输速度慢 ,UDP 是不可靠的但传输速度快。因此在选用具体协议通信时,应该根据通信数据的要求而决定。
若通信数据完整性需让位与通信实时性,则应该选用 TCP 协议(如文件传输、重要状态的更新等);反之,则使用 UDP 协议(如视频传输、实时通信等)。
案例代码及实现效果:
TCP:
客户端:
1 package cn.TCP; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.io.OutputStream; 7 import java.net.ServerSocket; 8 import java.net.Socket; 9 10 public class TCP_Clicent { 11 public static void main(String[] args) throws Exception { 12 //1.创建对象 13 ServerSocket sk=new ServerSocket(1122111); 14 //2.监听 15 Socket s=sk.accept(); 16 //打包数据 17 BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream())); 18 BufferedReader bw=new BufferedReader(new InputStreamReader(System.in)); 19 OutputStream os=s.getOutputStream(); 20 String line=null; 21 while((line=br.readLine())!=null){ 22 System.out.println("Client \t"+line); 23 os.write(bw.readLine().getBytes()); 24 } 25 //释放资源 26 s.close(); 27 //sk.close(); 28 } 29 }
服务器:
1 import java.io.BufferedReader; 2 import java.io.BufferedWriter; 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.io.InputStreamReader; 6 import java.io.OutputStreamWriter; 7 import java.net.Socket; 8 import java.net.UnknownHostException; 9 10 public class TCP_Service { 11 public static void main(String[] args) throws Exception { 12 Socket sk=new Socket("192.168.60.127",1122111); 13 BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 14 BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(sk.getOutputStream())); 15 String line=null; 16 while((line=br.readLine())!=null){ 17 bw.write(line); 18 bw.newLine(); 19 bw.flush(); 20 21 InputStream is=sk.getInputStream(); 22 byte [] by=new byte[1024]; 23 int num=is.read(by); 24 String h=new String(by, 0, num); 25 System.out.println("Service:\t"+h); 26 } 27 //br.close(); 28 //bw.close(); 29 sk.close(); 30 31 32 } 33 }
UDP:
客户端:
1 import java.io.BufferedReader; 2 import java.io.InputStreamReader; 3 import java.net.DatagramPacket; 4 import java.net.DatagramSocket; 5 import java.net.InetAddress; 6 import java.net.SocketException; 7 8 public class UDP_Clicent { 9 public static void main(String[] args) throws Exception { 10 DatagramSocket l=new DatagramSocket(); 11 DatagramSocket ds=new DatagramSocket(); 12 BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 13 String line=null; 14 byte [] bys=line.getBytes(); 15 int num=bys.length; 16 InetAddress address=InetAddress.getByName("192.168.60.127"); 17 int port=101236; 18 DatagramPacket dp=new DatagramPacket(bys,num, address,port); 19 ds.send(dp); 20 ds.close(); 21 } 22 }
服务器:
1 import java.net.DatagramPacket; 2 import java.net.DatagramSocket; 3 import java.net.InetAddress; 4 import java.net.SocketException; 5 6 public class UDP_Service { 7 8 public static void main(String[] args) throws Exception { 9 DatagramSocket ds=new DatagramSocket(101236); 10 byte[] bys = new byte[1024]; 11 int len = bys.length; 12 DatagramPacket dp = new DatagramPacket(bys, len); 13 ds.receive(dp); 14 byte[] by = dp.getData(); 15 int length = dp.getLength(); 16 InetAddress address = dp.getAddress(); 17 String ip = address.getHostAddress(); 18 String s = new String(by, 0, length); 19 System.out.println(ip + "---" + s); 20 ds.close(); 21 22 } 23 24 }