UDP报头结构 和注意事项

发布于:2024-05-06 ⋅ 阅读:(28) ⋅ 点赞:(0)

UDP协议

UDP这个协议的学习 ,最只要学习的就是报文格式
UDP数据报 = UDP报头 + UDP载荷

UDP协议端口格式

报头由4个部分组成 : 源端口号 、目的端口号、UDP长度、UDP校验和

UDP长度描述了整个UDP数据报,占多少个字节
通过UDP长度 就可以知道,当前载荷一共有多少个字节
UDP长度占两个字节 也就是0~65535 转化一下就是64kb ,一个UDP数据报,最长就是64kb,不能更长了 他的最大限制就是64kb

在这里假如面试官问你 : UDP数据报中,载荷最多能承载多少数据?
这里我们应该回答是64kb 而不是 64kb-8 .

校验和

数据在网络传输中,是可能会“出错的” ,可能会发生“比特翻转” 就是 本来数据想传过去1 但是到了接收方 就变成了 0 这就是发生了比特翻转
这就需要我们能够有办法 对传输的数据进行校验
第一层: 能够识别出 是否出错了
第二层: 最好能发现哪一位出错 ,并且能够进行纠错 但是这一层 往往需要消耗的时间和空间会更多

校验和 就是拿着数据进行一系列计算 ,得到结果,如果数据部分发生改变,此时得到的结果也就会不一样
就比如 现在有主机A和主机B 主机A给主机B发送一个数据 主机A先通过算法算出校验和 A 发送给B B再按照和A相同的算法算出校验和2,再把自己算出来的校验和2 和收到的校验和 比较是否一致

UDP中使用的是CRC算法作为校验和
CRC是一种简单粗暴的计算校验和的方式,循环冗余校验

就比如设定2个字节的变量,把数据的每个字节取出来,往这个变量上进行累加,假如结果溢出 ,超过了2个字节 溢出部分全部删除。

UDP的特点

全双工

UDP也就是说既能读 ,也能写 而相反的就是半双工 读和写只能一个

不可靠

就是UDP 发送方发送数据报之后,如果由于一些网络故障等原因没有把数据发送给对方 此时UDP协议层也不会给应用层发送任何错误信息 没用任何的安全机制 这里的可靠和不可靠 和 有无连接没有多大关系

无连接

就是知道 接收方的端口号和IP地址就可以直接进行传输 不需要进行连接

缓冲区

UDP没有正在意义上的发送缓冲区 发送的数据会直接给到内核处理 ,UDP有接收缓冲区,但是这个接收缓冲区收到的数据和发送的数据报的顺序是否一致 。还有 UDP的大小是受限的 UDP最大的传输的数据长度为64kb

高频面试题: UDP和TCP的区别

在这里插入图片描述

通过UDP实现单词查询 (网络编程)

UDP服务器:

package network;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class UDPEchoServer {
    private DatagramSocket socket = null;
    public  UDPEchoServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动");
        while (true) {
            //1 读取请求并解析
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(requestPacket);
            //为了方便打印  把二进制数据转为字符串String
            String request = new String(requestPacket.getData(),0,requestPacket.getLength());

            //根据请求计算回响
            String response = this.process(request);
            //把响应写回到客户端
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),0,response.getBytes().length,requestPacket.getSocketAddress());
            socket.send(responsePacket);
            System.out.printf("[%s,%d] req = %s,resp = %s\n",requestPacket.getAddress(),requestPacket.getPort(),request,response);
        }
    }

    public String process(String request) {
        //回显服务器
        return request;
    }

    public static void main(String[] args) throws IOException {
        UDPEchoServer server = new UDPEchoServer(9090);
        server.start();
    }
}

服务器子类:

package network;

import java.io.IOException;
import java.net.SocketException;
import java.util.HashMap;

public class UdpDictServer extends UDPEchoServer{

    //创建一个哈希表
    private HashMap<String,String> dict = null;
    public UdpDictServer(int port) throws SocketException {
        super(port);
        dict = new HashMap<>();
        dict.put("Animal","动物");
        dict.put("apple","苹果");
        dict.put("hello","你好");
        dict.put("bonus","红利");
    }

    //重写process方法

    @Override
    public String process(String request) {
        return dict.getOrDefault(request,"没有该单词");
    }

    public static void main(String[] args) throws IOException {
        UdpDictServer server = new UdpDictServer(9090);
        server.start();
    }
}

客户端:

package network;

import java.io.IOException;
import java.net.*;
import java.util.Scanner;

public class UdpEchoClient {
    private DatagramSocket socket = null;
    private String serverIp;
    private int serverPort;

    public UdpEchoClient(String serverIp,int serverPort) throws SocketException {
        socket = new DatagramSocket();
         this.serverIp = serverIp;
         this.serverPort =  serverPort;
    }

    public void start() throws IOException {
        System.out.println("客户端启动!");
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.print("请输入要发送的请求:");
            String request = scanner.next();  //从控制台中读取用户输入
            //构造请求并发送  有数据 也要有目标
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),0,request.getBytes().length, InetAddress.getByName(serverIp),serverPort);
            socket.send(requestPacket);  //发送请求
            //读取响应数据
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(responsePacket);
            //显示响应到控制台
            String response = new String(responsePacket.getData(),0,responsePacket.getLength());
            System.out.println(response);
        }
    }

    public static void main(String[] args) throws IOException {
        UdpEchoClient client = new UdpEchoClient("127.0.0.1",9090);
        client.start();
    }
}

上面就是本篇文章的全部内容 !谢谢大家的浏览!!!