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();
}
}
上面就是本篇文章的全部内容 !谢谢大家的浏览!!!