1. UDP收发的基本操作
数据报的大小限制在64K之内。
- 报文的接收
System.out.println("接收方启动中.....");
// 1、使用DatagramSocket 指定端口 创建接收端
DatagramSocket server =new DatagramSocket(6666); //服务器端侦听的端口
// 2、准备容器 封装成DatagramPacket 包裹
byte[] container =new byte[1024*60];
DatagramPacket packet = new DatagramPacket(container,0,container.length);
// 3、阻塞式接收包裹receive(DatagramPacket p)
server.receive(packet); //阻塞式
// 4、分析数据
// byte[] getData()
// getLength()
byte[] datas =packet.getData();
int len = packet.getLength();
System.out.println(new String(datas,0,len));
// 5、释放资源
server.close();
- 报文的发送
System.out.println("发送方启动中.....");
// 1、使用DatagramSocket 指定端口 创建发送端
DatagramSocket client =new DatagramSocket(8888); //发送端的源端口
//2、准备数据 一定转成字节数组
String data = "黑夜给了我黑色的眼睛";
byte[] datas = data.getBytes("UTF8");
//3、 封装成DatagramPacket 包裹,需要指定目的地
DatagramPacket packet =new DatagramPacket(datas,0,datas.length,
new InetSocketAddress("localhost",6666)); //发送端的目的地址和端口号
//4、发送包裹send(DatagramPacket p) *
client.send(packet);
// 5、释放资源
client.close();
- 如何在eclipse中开启多个console窗口
拖动调整Console窗口的位置,然后钉住
选择console控制台窗口
2. UDP收发基本数据类型
- 报文的接收
System.out.println("接收方启动中.....");
// 1、使用DatagramSocket 指定端口 创建接收端
DatagramSocket server =new DatagramSocket(6666);
// 2、准备容器 封装成DatagramPacket 包裹
byte[] container =new byte[1024*60];
DatagramPacket packet = new DatagramPacket(container,0,container.length);
// 3、阻塞式接收包裹receive(DatagramPacket p)
server.receive(packet); //阻塞式
// 4、分析数据 将字节数组还原为对应的类型
// byte[] getData()
// getLength()
byte[] datas =packet.getData();
int len = packet.getLength();
DataInputStream dis =new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(datas)));
//顺序与写出一致
String msg = dis.readUTF();
int age = dis.readInt();
boolean flag = dis.readBoolean();
char ch = dis.readChar();
System.out.println(msg+"-->"+flag);
// 5、释放资源
server.close();
- 报文的发送
System.out.println("发送方启动中.....");
// 1、使用DatagramSocket 指定端口 创建发送端
DatagramSocket client =new DatagramSocket(8888);
//2、准备数据 一定转成字节数组
//写出
ByteArrayOutputStream baos =new ByteArrayOutputStream();
DataOutputStream dos =new DataOutputStream(new BufferedOutputStream(baos));
//操作数据类型 +数据
dos.writeUTF("编码辛酸泪");
dos.writeInt(18);
dos.writeBoolean(false);
dos.writeChar('a');
dos.flush();
byte[] datas =baos.toByteArray();
//3、 封装成DatagramPacket 包裹,需要指定目的地
DatagramPacket packet =new DatagramPacket(datas,0,datas.length,
new InetSocketAddress("localhost",6666));
//4、发送包裹send(DatagramPacket p) *
client.send(packet);
// 5、释放资源
client.close();
3. UDP收发对象
- 报文的接收
System.out.println("接收方启动中.....");
// 1、使用DatagramSocket 指定端口 创建接收端
DatagramSocket server =new DatagramSocket(6666);
// 2、准备容器 封装成DatagramPacket 包裹
byte[] container =new byte[1024*60];
DatagramPacket packet = new DatagramPacket(container,0,container.length);
// 3、阻塞式接收包裹receive(DatagramPacket p)
server.receive(packet); //阻塞式
// 4、分析数据 将字节数组还原为对应的类型
byte[] datas =packet.getData();
int len = packet.getLength();
//读取 -->反序列化
ObjectInputStream ois =new ObjectInputStream(new BufferedInputStream(new ByteArrayInputStream(datas)));
//顺序与写出一致,对象的数据还原
Object str = ois.readObject();
Object date = ois.readObject();
Object employee = ois.readObject();
if(str instanceof String) {
String strObj = (String) str;
System.out.println(strObj);
}
if(date instanceof Date) {
Date dateObj = (Date) date;
System.out.println(dateObj);
}
if(employee instanceof Employee) {
Employee empObj = (Employee) employee;
System.out.println(empObj.getName()+"-->"+empObj.getSalary());
}
// 5、释放资源
server.close();
- 报文的发送
System.out.println("发送方启动中.....");
// 1、使用DatagramSocket 指定端口 创建发送端
DatagramSocket client =new DatagramSocket(8888);
//2、准备数据 一定转成字节数组
//写出
ByteArrayOutputStream baos =new ByteArrayOutputStream();
ObjectOutputStream oos =new ObjectOutputStream(new BufferedOutputStream(baos));
//对象
oos.writeObject("我却用它来寻找光明");
oos.writeObject(new Date());
Employee emp =new Employee("欧阳克",400);
oos.writeObject(emp);
oos.flush();
byte[] datas =baos.toByteArray();
//3、 封装成DatagramPacket 包裹,需要指定目的地
DatagramPacket packet =new DatagramPacket(datas,0,datas.length,
new InetSocketAddress("localhost",6666));
//4、发送包裹
client.send(packet);
// 5、释放资源
client.close();
4. 传输文件(小文件)
- 工具类
public class IOUtils {
/**
* 1、图片读取到字节数组
* 1)、图片到程序 FileInputStream
* 2)、程序到字节数组 ByteArrayOutputStream
*/
public static byte[] fileToByteArray(String filePath) {
//1、创建源与目的地
File src = new File(filePath);
byte[] dest =null;
//2、选择流
InputStream is =null;
ByteArrayOutputStream baos =null;
try {
is =new FileInputStream(src);
baos = new ByteArrayOutputStream();
//3、操作 (分段读取)
byte[] flush = new byte[1024*10]; //缓冲容器
int len = -1; //接收长度
while((len=is.read(flush))!=-1) {
baos.write(flush,0,len); //写出到字节数组中
}
baos.flush();
return baos.toByteArray();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、释放资源
try {
if(null!=is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 2、字节数组写出到图片
* 1)、字节数组到程序 ByteArrayInputStream
* 2)、程序到文件 FileOutputStream
*/
public static void byteArrayToFile(byte[] src,String filePath) {
//1、创建源
File dest = new File(filePath);
//2、选择流
InputStream is =null;
OutputStream os =null;
try {
is =new ByteArrayInputStream(src);
os = new FileOutputStream(dest);
//3、操作 (分段读取)
byte[] flush = new byte[5]; //缓冲容器
int len = -1; //接收长度
while((len=is.read(flush))!=-1) {
os.write(flush,0,len); //写出到文件
}
os.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、释放资源
try {
if (null != os) {
os.close();
}
} catch (Exception e) {
}
}
}
}
- 文件的接收
System.out.println("接收方启动中.....");
// 1、使用DatagramSocket 指定端口 创建接收端
DatagramSocket server =new DatagramSocket(6666);
// 2、准备容器 封装成DatagramPacket 包裹
byte[] container =new byte[1024*60];
DatagramPacket packet = new DatagramPacket(container,0,container.length);
// 3、阻塞式接收包裹receive(DatagramPacket p)
server.receive(packet); //阻塞式
// 4、分析数据 将字节数组还原为对应的类型
// byte[] getData()
// getLength()
byte[] datas =packet.getData();
int len = packet.getLength();
IOUtils.byteArrayToFile(datas, "src/copy.png");
// 5、释放资源
server.close();
- 文件的发送
System.out.println("发送方启动中.....");
// 1、使用DatagramSocket 指定端口 创建发送端
DatagramSocket client =new DatagramSocket(8888);
//2、准备数据 一定转成字节数组
byte[] datas =IOUtils.fileToByteArray("src/logo.png");
//3、 封装成DatagramPacket 包裹,需要指定目的地
DatagramPacket packet =new DatagramPacket(datas,0,datas.length,
new InetSocketAddress("localhost",6666));
//4、发送包裹send(DatagramPacket p) *
client.send(packet);
// 5、释放资源
client.close();
5. 多次发送,多次接收
- 接收端
System.out.println("接收方启动中.....");
// 1、使用DatagramSocket 指定端口 创建接收端
DatagramSocket server =new DatagramSocket(6666);
while(true) {
// 2、准备容器 封装成DatagramPacket 包裹
byte[] container =new byte[1024*60];
DatagramPacket packet = new DatagramPacket(container,0,container.length);
// 3、阻塞式接收包裹receive(DatagramPacket p)
server.receive(packet); //阻塞式
// 4、分析数据
// byte[] getData()
// getLength()
byte[] datas =packet.getData();
int len = packet.getLength();
String data=new String(datas,0,len);
System.out.println(data);
if(data.equals("bye")) {
break;
}
}
// 5、释放资源
server.close();
- 发送端
System.out.println("发送方启动中.....");
// 1、使用DatagramSocket 指定端口 创建发送端
DatagramSocket client =new DatagramSocket(8888);
//2、准备数据 一定转成字节数组
BufferedReader reader =new BufferedReader(new InputStreamReader(System.in));
while(true) {
String data = reader.readLine();
byte[] datas = data.getBytes();
//3、 封装成DatagramPacket 包裹,需要指定目的地
DatagramPacket packet =new DatagramPacket(datas,0,datas.length,
new InetSocketAddress("localhost",6666));
//4、发送包裹send(DatagramPacket p) *
client.send(packet);
if(data.equals("bye")) {
break;
}
}
// 5、释放资源
client.close();
6. 全双工通信
引入多线程
- 接收器
public class TalkReceive implements Runnable {
private DatagramSocket server;
private String from;
public TalkReceive(int port, String from) {
this.from = from;
try {
server = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
byte[] container = new byte[1024 * 60];
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
try {
server.receive(packet);// 阻塞式接收
byte[] datas = packet.getData();
int len = packet.getLength();
String data = new String(datas, 0, len);
System.out.println(from + ":" + data);
if (data.equals("bye")) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
server.close();
}
}
- 发送器
public class TalkSend implements Runnable {
private DatagramSocket client;
private BufferedReader reader;
private String destIP;
private int destPort;
public TalkSend(int srcPort, String destIP, int destPort) {
this.destIP = destIP;
this.destPort = destPort;
try {
client = new DatagramSocket(srcPort);
reader = new BufferedReader(new InputStreamReader(System.in));
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
String data;
try {
data = reader.readLine(); // 阻塞读取控制台输入
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas, 0, datas.length,
new InetSocketAddress(this.destIP, this.destPort));
client.send(packet);
if (data.equals("bye")) {
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
client.close();
}
}
- 对等通信端(屌丝 )
new Thread(new TalkSend(6100, "localhost", 8847)).start(); // 发送
new Thread(new TalkReceive(8848, "长腿皮裤妹")).start(); // 接收
- 对等通信端(长腿皮裤妹)
new Thread(new TalkSend(6120, "localhost", 8848)).start(); // 发送
new Thread(new TalkReceive(8847, "屌丝")).start(); // 接收