首先,UDP协议是一种不可靠的网络协议,它在通信的两端各建立一个Socket对象,但是这两个Socket只是发送,接收数据的对象,因此对于基于UDP协议的通信双方而言,没有所谓的客户端和服务器的概念。
UDP发送数据
构造方法
方法名 | 说明 |
DatagramSocket() | 创建数据报套接字并将其绑定到本机地址上的任何可用端口 |
DatagramPacket(byte[] buf,int len,InetAddress add,int port) | 创建数据包,发送长度为len的数据包到指定主机的指定端口 |
相关方法
方法名 | 说明 |
void send(DatagramPacket p) | 发送数据报包 |
void close() | 关闭数据报套接字 |
void receive(DatagramPacket p) | 从此套接字接受数据报包 |
- 发送数据的步骤
- 创建发送端的Socket对象(DatagramSocket)
- 创建数据,并把数据打包
- 调用DatagramSocket对象的方法发送数据
- 关闭发送端
UDP接收数据
构造方法
方法名 | 说明 |
DatagramPacket(byte[] buf, int len) | 创建一个DatagramPacket用于接收长度为len的数据包 |
相关方法
方法名 | 说明 |
byte[] getData() | 返回数据缓冲区 |
int getLength() | 返回要发送的数据的长度或接收的数据的长度 |
- 接收数据的步骤
- 创建接收端的Socket对象(DatagramSocket)
- 创建一个数据包,用于接收数据
- 调用DatagramSocket对象的方法接收数据
- 解析数据包,并把数据在控制台显示
- 关闭接收端
案例:UDP实现多线程在线聊天
发送类
//定义一个发送端类继承 Runnable接口
public class TalkSendDemo implements Runnable{
DatagramSocket socket=null;
BufferedReader bf = null;
private int fromPort;
private String toIP;
private int toPort;
//构造方法
public TalkSendDemo(int fromPort, String toIP, int toPort) {
this.fromPort = fromPort;//定义从哪个端口发过来(ps:其实并不重要,因为你只要知道你往哪发就行了
this.toIP = toIP;//定义接收方的IP地址
this.toPort = toPort;//定义接收方的端口号
try {
socket = new DatagramSocket(fromPort);//创建发送端的Socket对象(DatagramSocket)
bf = new BufferedReader(new InputStreamReader(System.in));//从键盘输入字符
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
//为了保持一直发送,用一个While写死!
while(true){
try {
String s = bf.readLine();
byte[] bytes = s.getBytes();
//发送数据
DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length,new InetSocketAddress(this.toIP,this.toPort));
socket.send(packet);
if(s.equals("bye")){
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
//这边不写if语句就会报错,因为你不给一个结束循环的条件的话,这句话就会永远执行不了,所以就会出来unreachable statement错误
socket.close();
}
}
接收类
//定义一个接收端的类 继承Runnable接口
public class TalkReceiveDemo implements Runnable {
DatagramSocket socket =null;
private int Port;
private String name;
public TalkReceiveDemo(int Port, String name) {
this.Port = Port;
= name;
try {
socket = new DatagramSocket(Port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
byte[] bytes = new byte[1024];
while (true){
DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length);
try {
socket.receive(packet);
} catch (IOException e) {
e.printStackTrace();
}
byte[] data = packet.getData();
String s = new String(data, 0, data.length);
System.out.println(+":"+s);
if (s.equals("bye")){
break;
}
}
socket.close();
}
学生线程
//定义一个学生线程
public class StudentThread {
//确实从哪个端口发过来不重要,重要的是,你发往哪个端口,以及接收方当前端口,这两个端口应该是一致的
public static void main(String[] args) {
// new Thread(new TalkSendDemo("localhost",8090)).start();
// new Thread(new TalkReceiveDemo(8889,"老师")).start();
new Thread(new TalkSendDemo("localhost",18880)).start();
new Thread(new TalkReceiveDemo(18081,"老师")).start();
}
}
老师线程
//定义老师线程
public class TeacherThread {
public static void main(String[] args) {
new Thread(new TalkSendDemo("localhost",18081));
new Thread(new TalkReceiveDemo(18880,"学生")).start();
}
}
实现效果