当前位置:   article > 正文

UDP协议(UDP协议特点 UDP的报文格式 UDP的服务端和客户端代码(简单的步骤))_udp服务端系统流程图

udp服务端系统流程图

目录

端口号 

UDP协议

UDP协议特点

UDP 无连接  

 UDP 面向数据报 

UDP 全双工  

UDP 的报文格式 

什么是校验和?

如何基于校验和来完成数据校验呢?

CRC算法(循环冗余算法) 

MD5算法/SHA算法(这里只介绍MD5算法(工作中常用))

UDP的服务端和客户端代码(简单的步骤例子) 

UDP的服务端 

UDP的客户端 

 


 

本篇主要介绍传输层(TCP/IP五层(或四层)模型)中的 UDP协议

想要详细了解UDP的内容,我们还需要了解一个概念 —— 端口号

端口号 

写一个服务器,必须手动指定一个端口号,通过端口来区分当前这个主机上的不同的应用程序;写一个客户端,当客户端在通信的时候也会有一个端口号(代码中感受不到),系统自动分配。 

端口号,固定就是占2个字节的 . 意味着,端口号表示的数据范围就是 0 ~ 65535(一般 0 不使用)

1~1023 称为 "知名端口号"

1024~65535 是我们普通的端口号

 "知名端口号" :就是给一些比较 ”知名“ 的服务器,预留一个 ”位置“,但事实上,这些所谓的 ”知名“ 服务器,现在大部分都已经不再使用了

其中几个,到现在仍然知名的端口:

22:ssh 服务器的端口号 (ssh协议是用来登录远程主机的)

80:http 服务器的端口号

443:https 服务器的端口号

......

 我们要确保使用的端口号和别人的端口号不要重复

介绍完端口号,我们就可以来介绍 UDP了

UDP协议

UDP协议特点

UDP :无连接,不可靠,面向数据报,全双工 

UDP 无连接  

UDP 协议本身不会存储对端的信息,要在发送数据的时候,显示指定要传输给谁

 

 

不可靠,代码中体现不出来

 

 UDP 面向数据报 

 

UDP 全双工  

通过一个socket,既可以 send,又可以 receive 

 

(最底下有完整的代码) 

 

UDP 的报文格式 

学习一个协议,其中最主要的工作就是理解协议的报文格式 

 

ps:源ip, 目的ip 在 网络层 

 

什么是校验和?

计算机中非常广泛使用的概念

前提:网络传输中,由于一些外部的干扰,就可能会出现数据传输出错的情况。

因此我们就要想办法,能够识别出出错的程序校验和,就是这样的一种检查手段。

校验和本质上是 一个字符串,体积比原始的数据更小,又是通过原始的数据生成的。

原始数据相同,得到的校验和就一定相同,反之,校验和相同,原始数据大概率相同(理论上存在不同的情况,但实际的概率非常低,忽略不计) 

如何基于校验和来完成数据校验呢?

1.发送方,把要发送的数据整理好 —— data1,然后通过一定的算法,计算出校验和 checksum1

2.发送方 把 data1 和 checksum1 一起通过网络发送出去

3.接收方收到数据,收到的数据称为 data2(此时的这个数据可能就和 data1 不一样了),还收到了checksum1

4.接收方再根据data2重新计算校验和(按照相同的算法),得到checksum2

5.对比 checksum1 和 checksum2 是否相同,如果不同,则认为data2 和 data1 一定不相同。如果相同,则认为 data1 和 data2 大概率是相同的(理论上存在不同的可能性,概率低,忽略)

 通过上面方式,就能发现数据传输出错

计算校验和,有很多种算法,此处UDP中使用的 CRC算法(循环冗余算法) 

 

CRC算法(循环冗余算法) 

就是把当前要计算 校验和 的数据的每个字节,都进行累加,把结果保存到这两个字节的变量中(累加过程中如果溢出了,也没关系)

如果中间某个数据,出现传输错误,第二次计算的 校验和 就会和第一次不同。

ps: CRC 这个算法其实不是特别靠谱,导致两个不同数据,得到相同的CRC校验和的概率比较大

(比如前一个字节恰好少个1,后一个字节恰好多个1,其实概率还是不大的,但确实有一定的风险) 

 

MD5算法/SHA算法(这里只介绍MD5算法(工作中常用))

 MD5算法 里有一系列的公式,来完成MD5的计算(咱们不需要考虑公式,这是给数学问题),但是咱们需要知道MD5 的特点

 MD5 的特点

1.定长:无论你原始数据多长,计算得到的MD5,都是固定长度 (这就很适配校验和,校验和就不应该太长,要不然不方便网络传输)

 

 

2.分散:给定两个原始 数据,哪怕绝大多数内容都一样,但只要有一个字节不同,得到的MD5值都会差异很大

 

  

3.不可逆:给你一个原始数据,计算MD5,非常容易,但是给你MD5,让你还原始数据,计算量非常庞大,以至于超出了现有计算机的算力极限,理论上是不可行的  

 

UDP的服务端和客户端代码(简单的步骤例子) 

UDP的服务端 

  1. package network;
  2. import java.io.IOException;
  3. import java.net.DatagramPacket;
  4. import java.net.DatagramSocket;
  5. import java.net.SocketException;
  6. public class UdpEchoServer {
  7. // 创建一个 DatagramSocket 对象. 后续操作网卡的基础.
  8. private DatagramSocket socket = null;
  9. public UdpEchoServer(int port) throws SocketException {
  10. // 这么写就是手动指定端口
  11. socket = new DatagramSocket(port);
  12. // 这么写就是让系统自动分配端口
  13. // socket = new DatagramSocket();
  14. }
  15. public void start() throws IOException {
  16. // 通过这个方法来启动服务器.
  17. System.out.println("服务器启动!");
  18. // 一个服务器程序中, 经常能看到 while true 这样的代码.
  19. while (true) {
  20. // 1. 读取请求并解析.
  21. DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
  22. socket.receive(requestPacket);
  23. // 当前完成 receive 之后, 数据是以 二进制 的形式存储到 DatagramPacket 中了.
  24. // 要想能够把这里的数据给显示出来, 还需要把这个二进制数据给转成字符串.
  25. String request = new String(requestPacket.getData(), 0, requestPacket.getLength());
  26. // 2. 根据请求计算响应(一般的服务器都会经历的过程)
  27. // 由于此处是回显服务器, 请求是啥样, 响应就是啥样.
  28. String response = process(request);
  29. // 3. 把响应写回到客户端.
  30. // 搞一个响应对象, DatagramPacket
  31. // 往 DatagramPacket 里构造刚才的数据, 再通过 send 返回.
  32. DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), response.getBytes().length,
  33. requestPacket.getSocketAddress());
  34. socket.send(responsePacket);
  35. // 4. 打印一个日志, 把这次数据交互的详情打印出来.
  36. System.out.printf("[%s:%d] req=%s, resp=%s\n", requestPacket.getAddress().toString(),
  37. requestPacket.getPort(), request, response);
  38. }
  39. }
  40. public String process(String request) {
  41. return request;
  42. }
  43. public static void main(String[] args) throws IOException {
  44. UdpEchoServer server = new UdpEchoServer(9090);
  45. server.start();
  46. }
  47. }

UDP的客户端 

  1. package network;
  2. import java.io.IOException;
  3. import java.net.*;
  4. import java.util.Scanner;
  5. public class UdpEchoClient {
  6. private DatagramSocket socket = null;
  7. private String serverIp = "";
  8. private int serverPort = 0;
  9. public UdpEchoClient(String ip, int port) throws SocketException {
  10. // 创建这个对象, 不能手动指定端口.
  11. socket = new DatagramSocket();
  12. // 由于 UDP 自身不会持有对端的信息. 就需要在应用程序里, 把对端的情况给记录下来.
  13. // 这里咱们主要记录对端的 ip 和 端口 .
  14. serverIp = ip;
  15. serverPort = port;
  16. }
  17. public void start() throws IOException {
  18. System.out.println("客户端启动!");
  19. Scanner scanner = new Scanner(System.in);
  20. while (true) {
  21. // 1. 从控制台读取数据, 作为请求
  22. System.out.print("-> ");
  23. String request = scanner.next();
  24. // 2. 把请求内容构造成 DatagramPacket 对象, 发给服务器.
  25. DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), request.getBytes().length,
  26. InetAddress.getByName(serverIp), serverPort);
  27. socket.send(requestPacket);
  28. // 3. 尝试读取服务器返回的响应了.
  29. DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);
  30. socket.receive(responsePacket);
  31. // 4. 把响应, 转换成字符串, 并显示出来.
  32. String response = new String(responsePacket.getData(), 0, responsePacket.getLength());
  33. System.out.println(response);
  34. }
  35. }
  36. public static void main(String[] args) throws IOException {
  37. UdpEchoClient client = new UdpEchoClient("127.0.0.1", 9090);
  38. //UdpEchoClient client = new UdpEchoClient("42.192.83.143", 9090);
  39. client.start();
  40. }
  41. }

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/179927
推荐阅读
相关标签
  

闽ICP备14008679号