目录
2.使用DatagramSocket类实现一个简单的单词翻译程序(包含客户端和服务端)
一.学习UDP的预备知识
1.熟悉网络通信中的五元组
(1)源IP地址和目的IP地址
确定发送消息的主机和接收消息的主机。
(2)源端口号和目的端口号
确定是该主机的哪个进程发送的消息和接收消息主机中的哪个进程。
端口号的划分:0~1023为知名端口号,有HTTP(80端口),HTTPS(443端口),FTP(21端口),SSH(22端口)等应用层协议。我们自己写程序时要避免知名端口号,以免发生异常。
1024~65535:操作系统动态分配的端口号,其中客户端的就是由操作系统从这个范围进行分配的。
其中一个进程可以绑定多个端口号,一个端口号不能被多个进程绑定
(3)协议号
发送消息的进程和接收的进程之间遵守的协议。
2.什么是客户端和服务端
二.socketAPI中UDP的使用
1.UDP在socket中使用的类和方法
其中使用到的类为DatagramSocket。常用的方法如下:
方法名 | 方法说明 |
DatagramSocket(int port,InetAddress laddr) | 创建一个数据报套接字,绑定到指定的本地地址 |
DatagramSocket(SocketAddress bindaddr) | 创建一个数据报套接字,绑定到指定的本地套接字地址 |
void bind(SocketAddress addr) | 将此DatagramSocket绑定到特定的地址和端口 |
void connect(InetAddress address, int port) | 将套接字连接到此套接字的远程地址 |
void receive(DatagramPacket p) | 从此套接字接收数据报包 |
void close() | 关闭此数据报套接字 |
void send(DatagramPacket p) | 从此套接字发送数据报包 |
在使用DatagramSocker中的数据是以数据报为单位进行发送的。
使用该类来进行发送数据报,这里使用到了以下两个构造器。
2.使用DatagramSocket类实现一个简单的单词翻译程序(包含客户端和服务端)
(1)图示
(2)代码实现
客户端:
这里还用到InetAddress 类下的一个静态方法
package javaweb.udptcp2.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;
public class UDPClient {
DatagramSocket socket = null;
String serverIp = null;
int serverPort;
//客户端的端口号不需要进行绑定,由系统自动分配
public UDPClient(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 sc = new Scanner(System.in);
while (true) {
String request = sc.nextLine();
//退出客户端
if("exit".equals(request)) {
break;
}
//构造要发送的数据报(这里将字符串数据转化为二进制来进行发送)
//InetAddres.getName()是确定主机名称的IP地址
DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length,
InetAddress.getByName(serverIp), serverPort);
//将构造好的数据报发送给指定的客户端
socket.send(requestPacket);
//以数据报的形式接收服务端的请求
DatagramPacket responPacket = new DatagramPacket(new byte[4096],4096);
socket.receive(responPacket);
//将接收到的消息转化为字符串(使用trim是去除字符串的前后空格)
String respons = new String(responPacket.getData(),0,responPacket.getLength()).trim();
//将得到的响应打印到控制台上
System.out.println(respons);
}
}
//启动客户端
public static void main(String[] args) throws IOException {
//这里的ip是本机的回环ip
UDPClient client = new UDPClient("127.0.0.1",9090);
client.start();
}
}
服务端:
package javaweb.udptcp2.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;
//实现一个简单的英文翻译的服务端
public class UDPServer {
DatagramSocket socket = null;
//保存单词
Map<String, String> words = new HashMap<>();
//给服务端需要绑定端口号
public UDPServer(int port) throws SocketException {
socket = new DatagramSocket(port);
words.put("猫","cat");
words.put("狗","dog");
words.put("鱼","fish");
}
//启动服务端
public void start() throws IOException {
System.out.println("服务端已经启动");
while (true) {
//接收客户端发来的请求
DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
socket.receive(requestPacket);
String request = new String(requestPacket.getData(),0,requestPacket.getLength()).trim();
//根据请求构造响应
String respons = process(request);
//将响应数据发送给客户端
DatagramPacket responsPacket = new DatagramPacket(respons.getBytes(),respons.getBytes().length,requestPacket.getSocketAddress());
socket.send(responsPacket);
//将服务端端发送给哪个客户端的数据输出到控制台上
System.out.printf("[%s:%d]; request:%s respons:%s\n",requestPacket.getAddress().toString()
,requestPacket.getPort(), request, respons);
}
}
//计算出的响应
private String process(String request) {
if(words.containsKey(request)) {
return words.get(request);
} else {
return "未找到";
}
}
//启动服务端
public static void main(String[] args) throws IOException {
UDPServer server = new UDPServer(9090);
server.start();
}
}
注意:这里数据报中的缓冲区是自己设置大小的,如果发送的数据超过缓冲区的大小则会自动截断,所以这里的大小需要自己配置。
(3)运行结果
三.UDP协议详情
1.UDP的协议端格式
协议格式详解图:
2.UDP的特点
- 无连接:知道对端的IP和端口号就直接进行传输, 不需要建立连接。
- 不可靠:没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP协议层也不会给应用层返回任何错误信息。
- 面向数据报:不能够灵活的控制读写数据的次数和数量。对于UDP传输,发送端如果发送了100字节的数据,那么接收端必须也一次接受100字节的数据,不能分开进行接收。
- 只有接收缓冲区没有发送缓冲区(发送缓冲区主要用于超时重传)。
- 大小受限,UDP所能传输数据的最大长度为64K。
3.了解基于UDP的一些应用层协议
- NFS: 网络文件系统
- TFTP: 简单文件传输协议
- DHCP: 动态主机配置协议
- BOOTP: 启动协议(用于无盘设备启动)
- DNS: 域名解析协议