1.UDP定义
UDP也叫用户数据协议【无连接的协议】
优点:不能保证数据的安全与可靠
缺点:消耗小,效率高
2.基于UDP的网络通讯程序需要的类和方法
基于UDP的网络通讯程序是不区分客户端和服务器。
(1)java.net.DatagramPacket【只负责创建用来发送的包和用来接收用的包】
该类表示数据报包。【打包被发送的数据/接收发来的数据】
构造方法:用来打包
DatagramPacket(byte[] buf, int length) 构造一个 DatagramPacket用于接收长度的数据包length。【接收发来的数据的数据包】
DatagramPacket(byte[] buf, int length, InetAddress address, int port【接收方的端口号】) 构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号。 【打包被发送的数据】
实例方法:用来解析
byte[] getData() 返回数据缓冲区。
int getLength() 返回要发送的数据的长度或接收到的数据的长度。
InetAddress getAddress() 返回该数据报发送或接收数据报的计算机的IP地址。
int getPort() 返回发送数据报的远程主机上的端口号,或从中接收数据报的端口号。【得到发送方的端口号】
(2)java.net.DatagramSocket【负责包的发送和包的接收】
此类表示用于发送和接收数据报数据包的套接字。
构造方法:
DatagramSocket() 构造数据报套接字并将其绑定到本地主机上的任何可用端口。【发包】
DatagramSocket(int port) 构造数据报套接字并将其绑定到本地主机上的指定端口。【收包】
实例方法:
void send(DatagramPacket p) 从此套接字发送数据报包。
void receive(DatagramPacket p) 从此套接字接收数据报包。
void close() 关闭此数据报套接字。
3. 基于UDP协议的通信程序创建步骤
(1)发送方:
- 将需要发送的数据通过DatagramPacket(byte[] buf, int length, InetAddress address, int port) 构造方法打包好。
- 通过DatagramSocket()的构造方法创建DatagramSocket对象。
- DatagramSocket对象的send方法将打包好的数据报包,发送。
- 关闭DatagramSocket。
(2)接收方:
- 通过DatagramSocket(int port)创建接收数据的DatagramSocket对象。
- 通过DatagramPacket(byte[] buf, int length) 创建一个空的数据报包。
- 通过调用接收数据的DatagramSocket对象的receive方法接收数据报包到空的数据报包。
- 解析数据报包。
- 关闭DatagramSocket。
4.代码演示
4.1客户端发,服务器收
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class ClientSendMain {
public static void main(String[] args) throws Exception{
//定义数据报包
DatagramPacket sendpacket=null;
InetAddress receiveaddress=null;
int port=3000;
BufferedReader buff=null;
DatagramSocket sendsocket=null;
/*
* 创建发送的包---数据打包----发送
*/
//键盘输入数据----准备发送的数据
System.out.println("请输入需要发送的数据:");
buff=new BufferedReader(new InputStreamReader(System.in));
String info = buff.readLine();
byte[] bytes = info.getBytes();
int length=bytes.length;
//本机地址
receiveaddress=InetAddress.getLocalHost();
//创建带有服务器地址和端口号的发送包
sendpacket=new DatagramPacket(bytes, length, receiveaddress, port);
//创建DatagramSocket对象
sendsocket=new DatagramSocket();
sendsocket.send(sendpacket);
sendsocket.close();
}
}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class ServerMain {
public static void main(String[] args) throws Exception {
/*
* 创建接收对象---创建接收用的空的数据报包-----解析
*/
//创建接收包的对象
int port=3000;
DatagramSocket receivesocket = new DatagramSocket(port);
//创建空的数据报包
byte buff[]=new byte[1024];
DatagramPacket receivepacket = new DatagramPacket(buff, buff.length);
//接收数据
receivesocket.receive(receivepacket);
//解析数据
byte data[] = receivepacket.getData();
int len=receivepacket.getLength();
String msg=new String(data,0,len);
String clientip = receivepacket.getAddress().getHostAddress();
int clientsendport = receivepacket.getPort();
System.out.println("接收到来自"+clientip+":"+clientsendport+"的消息:"+msg);
receivesocket.close();
}
}
4.2 客户端持续发,服务器持续收
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class ClientSendMain {
public static void main(String[] args) throws Exception {
BufferedReader buff = null;
InetAddress receiveaddress = null;
int serverport = 3000;
DatagramPacket sendpacket = null;
DatagramSocket sendsocket = null;
buff = new BufferedReader(new InputStreamReader(System.in));
sendsocket = new DatagramSocket();
receiveaddress = InetAddress.getLocalHost();
boolean flag = true;
while (flag) {
System.out.println("请输入需要发送的数据:");
String sendinfo = buff.readLine();
sendpacket = new DatagramPacket(sendinfo.getBytes(), sendinfo.getBytes().length, receiveaddress,
serverport);
sendsocket.send(sendpacket);
if (sendinfo.equals("exit")) {
flag=false;
}
}
sendsocket.close();
}
}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class ServerMain {
public static void main(String[] args) throws Exception {
DatagramSocket receivesocket = null;
DatagramPacket receivepacket = null;
String receivemsg = null;
int serverport = 3000;
String clientip = null;
int clientsendport = 0;
boolean flag = true;
receivesocket = new DatagramSocket(serverport);
byte buff[] = new byte[1024];
receivepacket = new DatagramPacket(buff, buff.length);
while (flag) {
receivesocket.receive(receivepacket);
byte data[] = receivepacket.getData();
int len = receivepacket.getLength();
receivemsg = new String(data, 0, len);
clientip = receivepacket.getAddress().getHostAddress();
clientsendport = receivepacket.getPort();
System.out.println("服务器接收到来自" + clientip + ":" + clientsendport + "的消息:" + receivemsg);
if(receivemsg.equals("exit")){
flag=false;
}
}
receivesocket.close();
}
}
4.3双向-客户端持续发和收,服务器持续收和发
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class ClientSendMain {
public static void main(String[] args) throws Exception {
//客户端发,需要的变量和对象
BufferedReader buff = null;
InetAddress receiveaddress = null;
int serverport = 3000;
DatagramPacket sendpacket = null;
DatagramSocket sendsocket = null;
buff = new BufferedReader(new InputStreamReader(System.in));
sendsocket = new DatagramSocket();
receiveaddress = InetAddress.getLocalHost();
//客户端收,需要的变量和对象
DatagramPacket receivepacket=null;
DatagramSocket receivesocket=null;
int receiveport=2000;
receivesocket=new DatagramSocket(receiveport);
byte bys[]=new byte[1024];
receivepacket=new DatagramPacket(bys,bys.length);
boolean flag = true;
while (flag) {
//发
System.out.println("请输入需要发送的数据:");
String sendinfo = buff.readLine();
sendpacket = new DatagramPacket(sendinfo.getBytes(), sendinfo.getBytes().length, receiveaddress,
serverport);
sendsocket.send(sendpacket);
//收
receivesocket.receive(receivepacket);
String receivemsg = new String( receivepacket.getData(), 0, receivepacket.getLength());
System.out.println("收到来自服务器返回的数据---"+receivemsg);
if (receivemsg.equals("exit")) {
flag=false;
}
}
sendsocket.close();
receivesocket.close();
}
}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class ServerMain {
public static void main(String[] args) throws Exception {
System.out.println("服务器已启动....");
//服务器收
DatagramSocket receivesocket = null;
DatagramPacket receivepacket = null;
int serverport = 3000;
receivesocket = new DatagramSocket(serverport);
byte buff[] = new byte[1024];
receivepacket = new DatagramPacket(buff, buff.length);
//服务器发
DatagramPacket sendpacket = null;
DatagramSocket sendsocket = null;
int sendport=2000;
InetAddress receiveaddress = InetAddress.getLocalHost();
sendsocket=new DatagramSocket();
boolean flag = true;
while (flag) {
//收
receivesocket.receive(receivepacket);
byte data[] = receivepacket.getData();
int len = receivepacket.getLength();
String receivemsg = new String(data, 0, len);
String clientip = receivepacket.getAddress().getHostAddress();
int clientsendport = receivepacket.getPort();
System.out.println("服务器接收到来自" + clientip + ":" + clientsendport + "的消息:" + receivemsg);
//发
sendpacket=new DatagramPacket(receivemsg.getBytes(),receivemsg.getBytes().length,receiveaddress,sendport);
sendsocket.send(sendpacket);
if(receivemsg.equals("exit")){
flag=false;
}
}
sendsocket.close();
receivesocket.close();
}
}
4.4 多个客户端持续发和收,服务器持续发和收
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;
/**
* 发送数据的客户端
*/
public class Client {
public static void main(String[] args) throws Exception {
BufferedReader buff = new BufferedReader(new InputStreamReader(System.in));
//绑定一个指定的端口用于接收数据和发送数据
DatagramSocket server=new DatagramSocket();
//定义接收数据的空包
byte[] sbyte=new byte[1024];
DatagramPacket spack=new DatagramPacket(sbyte, sbyte.length);
//定义持续控制发送的循环变量
boolean flag=true;
while (flag) {
System.out.println("请输入要发送的数据:");
String info=buff.readLine();
//打包数据
byte[] fbyte=info.getBytes();
DatagramPacket fpack=new DatagramPacket(fbyte, fbyte.length, InetAddress.getLocalHost(), 3000);
//发送数据
server.send(fpack);
//判断退出
if (info.equals("886")) {
flag=false;
System.out.println("关闭客户端!");
}else{
//接收数据
server.receive(spack);
//拆包
byte data[]=spack.getData();
String msg=new String(data,0,spack.getLength());
System.out.println("接收到服务器返回的数据是:"+msg);
}
}
server.close();
}
}
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/**
* 接收数据的服务器端
*/
public class Server {
public static void main(String[] args) throws Exception {
//绑定接收数据的端口
DatagramSocket server=new DatagramSocket(3000);
System.out.println("----》服务器端已经启动,等待客户端发送数据");
byte[] bytes = new byte[1024];
while(true){
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
server.receive(packet);
ClientThread clientThread=new ClientThread(server,packet);
Thread th=new Thread(clientThread);
th.start();
}
}
}
/**
* 用户发送数据线程类
*/
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class ClientThread implements Runnable{
private DatagramSocket server;
private DatagramPacket datagramPacket;
private boolean falg=true;
public ClientThread(DatagramSocket server,DatagramPacket datagramPacket ) {
this.server=server;
this.datagramPacket=datagramPacket;
}
public void run() {
try{
while(falg){
//拆包
byte data[]=datagramPacket.getData();
int len=datagramPacket.getLength();
String info=new String(data,0,len);
String clientip = datagramPacket.getAddress().getHostAddress();
int clientsendport = datagramPacket.getPort();
System.out.println("服务器接收到来自" + clientip + ":" + clientsendport + "的消息:" + info);
//判断退出
if (info.equals("886")) {
falg=false;
//server.close();
System.out.println("客户端退出");
}else{
//发送数据
info="server:"+info;
byte fbyte[]=info.getBytes();
DatagramPacket fPacket=new DatagramPacket(fbyte, fbyte.length,datagramPacket.getAddress(),datagramPacket.getPort());
server.send(fPacket);
falg=false;
}
}
//关闭
}catch(Exception e){
e.printStackTrace();
}
}
}