一、UDP 无连接的 高效的 基于数据报的 不可靠 的连接
主要的应用场景:
需要资源少,网络情况稳定的内网,或者对于丢包不敏感的应用,比如 DHCP 就是基于 UDP 协议的。
不需要一对一沟通,建立连接,而是可以广播的应用。因为它不面向连接,所以可以做到一对多,承担广播或者多播的协议。
需要处理速度快,可以容忍丢包,但是即使网络拥塞,也毫不退缩,一往无前的时候
基于 UDP 的几个例子
直播。直播对实时性的要求比较高,宁可丢包,也不要卡顿的,所以很多直播应用都基于 UDP 实现了自己的视频传输协议
实时游戏。游戏的特点也是实时性比较高,在这种情况下,采用自定义的可靠的 UDP 协议,自定义重传策略,能够把产生的延迟降到最低,减少网络问题对游戏造成的影响
物联网。一方面,物联网领域中断资源少,很可能知识个很小的嵌入式系统,而维护 TCP 协议的代价太大了;另一方面,物联网对实时性的要求也特别高。比如 Google 旗下的 Nest 简历 Thread Group,推出了物联网通信协议 Thread,就是基于 UDP 协议的
服务器端:
//服务器端 try { DatagramSocket ds= new DatagramSocket(8887); // byte [] b= new byte[1024]; DatagramPacket dp= new DatagramPacket(b, b.length); ds.receive(dp); System.out.println("客户端说:"+new String(dp.getData(),0,dp.getData().length)); //回复客户端消息 要回复的地址 原来的包裹上都有 //要定义 包裹的大小 和邮寄的地址 String str= "我去洗澡了"; SocketAddress address = dp.getSocketAddress(); DatagramPacket dp1= new DatagramPacket(str.getBytes(), str.getBytes().length, address); ds.send(dp1); //关闭资源。。。。。 ds.close(); } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
客户端:
//udp 就很类似于我们生活中的发快递 try { // DatagramSocket ds= new DatagramSocket(); // 要发的包裹 str String str="在吗?"; //选择快递地址 InetAddress address = InetAddress.getByName("localhost"); //填写快递单 (要传输的报文的byte 数组 以及起始的位置 结束的位置 地址) DatagramPacket dp= new DatagramPacket(str.getBytes(), 0, str.getBytes().length, address, 8887); //发送包裹 ds.send(dp); //接受服务器返回的 报文数据 byte [] b= new byte[1024]; DatagramPacket dp1= new DatagramPacket(b, b.length); ds.receive(dp1); System.out.println("服务器说:"+new String(dp1.getData(),0,dp1.getData().length)); ds.close(); } catch (SocketException e) { e.printStackTrace(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
TCP:可靠的连接 面向连接 基于流 效率相对较低 安全
// 服务器端要先向设备申请端口号 以便接受客户端的数据流 ServerSocket ss = null; Socket s = null; InputStream inputStream = null; OutputStream outputStream = null; try { ss = new ServerSocket(9999); s = ss.accept(); inputStream = s.getInputStream(); byte[] b = new byte[inputStream.available()]; int len = 0; while ((len = inputStream.read(b)) != -1) { System.out.println(new String(b, 0, len)); } // 向客户端回应下 outputStream = s.getOutputStream(); outputStream.write("我要去洗澡了".getBytes()); outputStream.flush(); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭资源 try { if (outputStream != null) { outputStream.close(); } if (inputStream != null) { inputStream.close(); } if (s != null) { s.close(); } } catch (IOException e) { e.printStackTrace(); } }
//客户端 Socket s = null; OutputStream outputStream = null; InputStream inputStream =null; try { s = new Socket("localhost", 9999); outputStream = s.getOutputStream(); outputStream.write("在?".getBytes()); // outputStream.flush(); //关闭套接字 s.shutdownOutput(); //接受服务端的回应 inputStream = s.getInputStream(); BufferedReader bb= new BufferedReader(new InputStreamReader(inputStream)); String readLine = bb.readLine(); System.out.println(readLine); //下边的代码有问题 死循环 // byte [] b= new byte[1024]; // int len =0; // while ((len= inputStream.read(b))!=-1) { // System.out.println(new String(b, 0, len)); // } inputStream.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (outputStream != null) { outputStream.close(); } if (s != null) { s.close(); } } catch (IOException e) { e.printStackTrace(); } }
面试:
两者的区别
- TCP 是面向连接的,UDP 是面向无连接的
- UDP程序结构较简单
- TCP 是面向字节流的,UDP 是基于数据报的
- TCP 保证数据正确性,UDP 可能丢包
- TCP 保证数据顺序,UDP 不保证
TCP 为什么是可靠连接
- 通过 TCP 连接传输的数据无差错,不丢失,不重复,且按顺序到达。
- TCP 报文头里面的序号能使 TCP 的数据按序到达
- 报文头里面的确认序号能保证不丢包,累计确认及超时重传机制
- TCP 拥有流量控制及拥塞控制的机制