UDP:用户数据报协议
特点:
①无连接;②不可靠传输;③面向数据报;④全双工
TCP:传输控制协议
特点:
①有连接;②可靠传输;③面向字节流;④全双工
无连接:使用UDP通信的双方,不需要刻意保存对端的基本信息,不需要接收连接也能通信
(比如使用微信发送,及时他没有登录微信,我也可以将我的内容发送给他)
有连接:使用TCP通信的双方,则需要可以保存对端的基本信息,需要先接收连接才能通信
(比如打电话,要记录对方的电话号码,当我拨打电话时,对方必须接通才能进行通话)
不可靠传输:消息发送了,但是并不关注是否发送成功
可靠传输:消息发送了,不能百分百的发送到达对方,但是尽可能的传输过去
面向数据报:以一个UDP数据报为单位
面向字节流:以字节为单位传输,读写方式灵活
全双工:一条路径,双向通信
要想进行通信,需要有socket文件这样的对象,借助socket文件对象间接操作网卡
往这个socket文件里面写数据,相当于通过网卡发送数据;往这个socket文件里面读数据,相当于通过网卡接收消息
UDP数据报套接字变成
DatagramSocket 是UDP Socket,用于发送和接受UDP数据
对象 是一个socket对象
构造方法:
①DatagramSocket():
创建一个UDP数据包套接字的Socket,绑定到本机任意一个随机端口
(无参数的一般用于客户端,客户端不需要手动指定端口号,系统会自动分配)
②DategramSocket(int port):
创建一个UDP数据包套接字的Socket,绑定到本机指定的端口
(一般用于服务端,需要手动提供端口号)
方法:
①void receive():从套接字接收数据,若没有数据,receive会阻塞等待,直到有数据为止
②void send():从套接字中发送数据报
③void close():关闭数据包套接字
DatagramPacket是UDP Socket发送和接受数据的数据报
构造方法:
①DatagramPacket(byte[] buf,int length):
构造一个DatagramPacket用来接收数据报,第一个参数是存放数据报的内容,第二个参数是这个数据包的长度
②DatagramPacket(byte[] buf,int offset.int length,SocketAddress address):
构造一个DatagramPacket用来发送数据报,第一个参数是数据报的内容,第二个参数是想要发送数据报内容的起始位置,第三个参数是想要发送的数据报长度,第四个参数是指定目的主机的端口号和ip
以UDP来实现一个简单的回显服务器
客户端发送一个请求,服务器响应一个一模一样的请求
同一个主机上,一个端口号同一时刻只能被一个进程使用

服务端:
public class UdpEchoSevert {
//要进行通信,必须要有socket对象
DatagramSocket socket = null;
//服务端要指定端口号,所以在构造方法中,创建socket对象并且指定绑定的端口号
public UdpEchoSevert(int port) throws SocketException {
socket = new DatagramSocket(port);
}
//服务器启动
public void star() throws IOException {
while(true) {
System.out.println("服务器启动:");
//1.读取请求并分析
//创建一个长度为4090的数据报,目前里面还没有存放东西
DatagramPacket requestPacket = new DatagramPacket(new byte[4090],4090);
socket.receive(requestPacket);//将读取到的信息放入到这个数据包中
//为了方便计算响应,将数据包转换成String类型
//requestPacket.getData()获取到数据包的内容,从0位置开始,到这个数据包的长度
String request = new String(requestPacket.getData(),0, requestPacket.getLength());
//2.根据请求计算响应
String respond = process(request);
//计算的响应结果放到响应的数据包中,构造响应要指定将这个数据报发送给谁
//respond.getBytes()响应结果内容的起始位置,respond.getBytes().length响应结果内容的长度
// requestPacket.getSocketAddress()获取到ip和端口号
DatagramPacket respondPacket = new DatagramPacket(respond.getBytes(),respond.getBytes().length,
requestPacket.getSocketAddress());
socket.send(respondPacket);
System.out.printf("[%s:%d] req: %s, rest: %s\n",requestPacket.getAddress().toString(),
requestPacket.getPort(),request,respond);
}
}
public static String process(String request) {
return request;
}
public static void main(String[] args) throws IOException {
UdpEchoSevert udpEchoSevert = new UdpEchoSevert(9090);
udpEchoSevert.star();
}
}
客户端:
public class UdpEchoClient {
//进行通信要有socket对象
private DatagramSocket socket = null;
private String severtIp;//ip
private int severtPort;//端口号
//构造socket对象,并且不需要手动指定端口号,在传输时需要明确ip和端口号
public UdpEchoClient(String severtIp,int severtPort) throws SocketException {
//客户端不需要手动指定要进行通信的端口号
socket = new DatagramSocket();
this.severtIp = severtIp;
this.severtPort = severtPort;
}
//
public void star() throws IOException {
//不断的发送请求
Scanner scanner = new Scanner(System.in);
while(true) {
//1.读取用户从控制台输入的数据
System.out.println("请输入:");
String request = scanner.nextLine();
//2.构造请求数据包并发送数据包
//request.getBytes()获取用户输入的内容 request.getBytes().length内容的的长度是数据包的长度
//构造发送数据报,要指定目的主机的ip和端口号
DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length,
InetAddress.getByName(severtIp),severtPort);
//客户端发送请求
socket.send(requestPacket);
//3.接受服务端的响应
DatagramPacket respondPacket = new DatagramPacket(new byte[4090],4090);
socket.receive(respondPacket);//receive将接受到的响应内放到respondPacket报里面
//4.将响应内容转化成字符串,显示在控制台上
String respond = new String(respondPacket.getData(),0,respondPacket.getLength());
System.out.printf("req : %s , resp : %s\n",request,respond);
}
}
public static void main(String[] args) throws IOException {
UdpEchoClient udpEchoClient = new UdpEchoClient("127.0.0.1",9090);
udpEchoClient.star();
}
}
服务端显示的结果:

客户端显示的结果:

文章对比了UDP和TCP协议的特点,包括无连接、不可靠传输、面向数据报等与TCP的有连接、可靠传输、面向字节流等特点。通过实例阐述如何使用DatagramSocket和DatagramPacket在Java中实现UDP回显服务器和客户端通信。

被折叠的 条评论
为什么被折叠?



