Java网络编程03

5.UDP网络通信编程[了解]

5.1基本介绍

  1. DatagramSocket DatagramPacket[数据报/数据包]实现了基于 UDP的协议网络程序
  2. UDP数据报通过数据报套接字DatagramSocket 发送和接收,系统不保证UDP数据报一定能够安全的送到目的地,也不确定什么时候可以抵达
  3. DatagramPacket 对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号,以及接收端的IP地址和端口号
  4. UDP协议中每个数据报都给出了完整的的地址信息,因此无需建立发送方和接收方的连接

UDP说明:

  • 没有明确的服务端可客户端,演变成数据的发送端和接收端
  • 接收数据和发送数据是通过DatagramSocket 对象完成的
  • 将数据封装到DatagramPacket 对象(装包)发送
  • 当接收到DatagramPacket 对象,需要进行拆包,取出数据
  • DatagramSocket 可以指定在某个端口接收数据

5.2基本流程和应用案例

  1. 核心的两个类/对象 DatagramSocket 与 DatagramPacket
  2. 建立发送端和接收端(没有服务端和客户端的概念)
  3. 建立数据报/包-DatagramPacket
  4. 调用DatagramSocket的发送、接收方法
  5. 关闭DatagramSocket

应用案例1:

  1. 编写一个接收端A和一个发送端B
  2. 接收端A在9999端口等待接收数据(receive)
  3. 发送端B向接收端A 发送数据 “hello,明天吃火锅~”
  4. 接收端A收到后,回复“好的,明天见”,然后退出
  5. 发送端B接收回复的信息,再退出

接收端UDPReceiverA:

package li.network.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress; //UDP接收端A
public class UDPReceiverA {
public static void main(String[] args) throws IOException { // 1.创建一个DatagramSocket对象,准备在9999端口 接收 数据
DatagramSocket datagramSocket = new DatagramSocket(9999); // 2.构建一个DatagramPacket对象,准备接收数据
//因为UDP的每个数据报限制在64k内
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length); //3. 调用接收方法,将通过网络传输的 DatagramPacket对象
// 填充到 packet对象中
// 当有数据报发送到本机的9999端口时,就会接收到数据
// 如果没有数据报发送到本机的 9999端口,就会阻塞等待
System.out.println("接收端A 等待接收数据...");
datagramSocket.receive(packet); //4.把 packet进行拆包,取出数据,并显示
int length = packet.getLength();//实际接收到的数据长度
byte[] data = packet.getData();//实际接收到的数据
String s = new String(data, 0, length);//构建字符串
System.out.println(s); //5. (发送)回复消息===
//bytes, bytes.length, InetAddress.getByName("192.168.1.6"), 8888
//分别对应 发送的内容 内容长度 对方的ip 对发的接收端口
byte[] bytes = "好的 明天见".getBytes();
DatagramPacket datagramPacket =
new DatagramPacket(bytes, bytes.length, InetAddress.getByName("192.168.1.6"), 8888);
datagramSocket.send(datagramPacket); //6.关闭资源
datagramSocket.close();
System.out.println("A端 退出");
}
}

发送端UDPSenderB:

package li.network.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress; //发送端B====>也可以接收数据
public class UDPSenderB {
public static void main(String[] args) throws IOException { //1.创建DatagramSocket ,准备在8888端口接收数据
//这里的端口是为了接收A回复的数据
DatagramSocket datagramSocket = new DatagramSocket(8888); //2.将需要发送的数据封装到 DatagramPacket对象
byte[] data = "hello 明天吃火锅".getBytes();
//说明封装的对象:
// data- 内容字节数组
// data.length- 字节数组的长度
// 主机(IP)-接收方的ip
// 9999 -对方用来接收数据的端口
DatagramPacket datagramPacket =
new DatagramPacket(data, data.length, InetAddress.getByName("192.168.1.6"), 9999);
datagramSocket.send(datagramPacket); //3.(接收)接收回信===
//3.1构建一个DatagramPacket对象,准备接收数据
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
//3.2调用receive接收方法,将通过网络传输的 DatagramPacket对象
// 填充到 packet对象中
// 当有数据报发送到本机的8888端口时,就会接收到数据
// 如果没有数据报发送到本机的 8888端口,就会阻塞等待
datagramSocket.receive(packet);
//拆包
int length = packet.getLength();//实际接收到的数据长度
byte[] bytes = packet.getData();//实际接收到的数据
String s = new String(bytes, 0, length);//构建字符串
System.out.println(s); //4.关闭资源
datagramSocket.close();
System.out.println("B端 退出");
}
}

先启动接收端A:

启动发送端B之后:


6.本章作业

6.1HomeWork01

  1. 使用字符流的方式,编写一个客户端程序和服务端程序
  2. 客户端程序发送“name”,服务端接收到后,返回“nova”
  3. 客户端发送“hobby”,服务端接收到后,返回 “打代码”
  4. 若客户端发送的是其他信息,则服务端回复“你说啥呢?”
  5. 可以循环问答

服务端Homework01Server:

package li.network.homework.homework01;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket; public class Homework01Server {
public static void main(String[] args) throws IOException {
//1.服务端 在9999端口等待连接...
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端:正在9999端口等待连接...");
Socket socket = serverSocket.accept(); BufferedReader br = null;
BufferedWriter bw = null;
int loop = 999; while ((loop--) != 0) {
//2.服务端接收数据
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String s = br.readLine();
System.out.println(s); //3.服务端发送数据
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
if (s.equals("来自客户端:你的名字?")) {
bw.write("来自服务端:我是jack");
} else if (s.equals("来自客户端:你的爱好?")) {
bw.write("来自服务端:打代码");
} else {
bw.write("来自服务端:你在说啥??");
}
bw.newLine();//写入结束标志
bw.flush();
} //4. 关闭流和socket
br.close();
bw.close();
socket.close();
serverSocket.close();
System.out.println("服务端退出..");
}
}

客户端Homework01Client:

package li.network.homework.homework01;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner; public class Homework01Client {
public static void main(String[] args) throws IOException {
//1.客户端连接服务端
//InetAddress.getByName("192.168.1.6"),9999
// --服务端ip和服务端的端口
Socket socket = new Socket(InetAddress.getByName("192.168.1.6"), 9999); BufferedReader br = null;
BufferedWriter bw = null;
int loop = 999; while ((loop--) != 0) {
//2.客户端发送数据
//从键盘读取用户问题
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你的问题:");
String question = scanner.next();
//数据 写入 数据通道
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("来自客户端:" + question);
bw.newLine();//结束写入标志
bw.flush(); //3.客户端接收数据
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String s = br.readLine();
System.out.println(s);
} //4.关闭流和socket
bw.close();
br.close();
socket.close();
System.out.println("客户端退出..");
}
}

6.2HomeWork02

  1. 编写一个接收端A和一个发送端B,使用UDP协议完成
  2. 接收端在8888端口等待接收数据(receive)
  3. 发送端向接收端 发送数据 “四大名著是哪些?”
  4. 接收在接收到 问题后,返回答案“《红楼梦》《三国演义》.... ”,否则就返回 ”what?“
  5. 接收端和发送端退出
  6. 最好可以循环问答

思路:

接收端Homework02ReceiverA:

package li.network.homework;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress; //接收端A
public class Homework02ReceiverA {
public static void main(String[] args) throws IOException {
//1.创建DatagramSocket对象,指定端口
// 9999:指定 接收数据的端口
DatagramSocket datagramSocket = new DatagramSocket(8888);
System.out.println("接收端A 等待接收数据..."); int loop = 999;
while ((loop--) != 0) {
//2.接收信息
//2.1构建一个DatagramPacket对象,用来装入接收到的 DatagramPacket
byte[] buf = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length);
//2.2使用receive接收数据
datagramSocket.receive(datagramPacket);
//2.3取出内容--拆包
byte[] data = datagramPacket.getData();//真正接收到的内容
int length = datagramPacket.getLength();//内容的长度,用于构建字符串
String s = new String(data, 0, length);//构建字符串
System.out.println(s); //3.发送回信
byte[] databack = null;
if (s.equals("四大名著是那些?")) {
//封装要发送的信息,放到DatagramPacket对象中
databack = "红楼梦、三国演义、水浒传、西游记".getBytes();
} else {
databack = "what???".getBytes();
}
//在DatagramPacket对象指明发送的内容、长度、接收方的ip地址、接收方的端口
DatagramPacket datagramPacket2 =
new DatagramPacket(databack, databack.length, InetAddress.getByName("192.168.1.6"), 9999);
datagramSocket.send(datagramPacket2);
} //4.关闭sock
datagramSocket.close();
System.out.println("接收端A 退出"); }
}

发送端Homework02SenderB:

package li.network.homework;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner; //发送端B
public class Homework02SenderB {
public static void main(String[] args) throws IOException { //1.创建DatagramSocket ,准备在8888端口接收数据
//这里的端口是为了接收A回复的数据
DatagramSocket datagramSocket = new DatagramSocket(9999); int loop = 999;
while ((loop--) != 0) {
//2.发送数据
//2.1从键盘获取问题
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你的问题:");
String question = scanner.next();
//2.2将需要发送的数据封装到 DatagramPacket对象
//在DatagramPacket对象指明发送的内容、长度、接收方的ip地址、接收方的端口
byte[] data = question.getBytes();
DatagramPacket datagramPacket =
new DatagramPacket(data, data.length, InetAddress.getByName("192.168.1.6"), 8888);
datagramSocket.send(datagramPacket); //3.接收数据
//3.1先构建一个DatagramPacket对象,用来装入接收到的 DatagramPacket
byte[] buf = new byte[1024];
DatagramPacket datagramPacket2 = new DatagramPacket(buf, buf.length);
//3.2取出内容--拆包
datagramSocket.receive(datagramPacket2);
byte[] data2 = datagramPacket2.getData();//接收到的真正内容
int length = datagramPacket2.getLength();//内容的长度
String s = new String(data2, 0, length);
System.out.println(s);
} //4.关闭socket
datagramSocket.close();
System.out.println("发送端B 退出"); }
}

6.3Homework03

  1. 编写一个客户端程序和服务端程序
  2. 客户端可以输入一个 音乐文件名,比如高山流水, 服务端收到音乐名后,可以给客户端返回这个音乐文件,如果服务器没有这个文件,则返回一个默认的音乐即可
  3. 客户端收到文件后,保存到本地d盘
  4. 提示:该客户端可以使用StreamUtils.java

本质:其实就是指定下载文件的应用

思路:

day41-网络编程03的更多相关文章

  1. Python网络编程03 /缓存区、基于TCP的socket循环通信、执行远程命令、socketserver通信

    Python网络编程03 /缓存区.基于TCP的socket循环通信.执行远程命令.socketserver通信 目录 Python网络编程03 /缓存区.基于TCP的socket循环通信.执行远程命 ...

  2. day36 Pyhton 网络编程03

    一.内容回顾 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...

  3. day41 网络编程

    目录 网络架构 单机架构 CS架构 BS架构 互联网和互联网的组成(教材版) 边缘部分: 核心部分: 互联网的组成 硬件 软件 打开网页的过程(科普版) 物理层 数据链路层 网络层 传输层 抽象层 网 ...

  4. Linux网络编程学习路线

    转载自:https://blog.csdn.net/lianghe_work/article 一.网络应用层编程   1.Linux网络编程01——网络协议入门 2.Linux网络编程02——无连接和 ...

  5. 【Linux】 Linux网络编程

    作者:李春港 出处:https://www.cnblogs.com/lcgbk/p/14779410.html 目录 前言 (一). 回顾系统编程进程的通信方式 (二). 网络编程大纲 (三). 网络 ...

  6. 【TCP/IP网络编程】:03地址族与数据序列

    上一篇文章介绍了套接字的创建过程,这篇文章主要讨论分配给套接字的IP地址和端口号的相关知识. IP地址和端口号 IP(Internet Protocol,网络协议)地址是收发网络数据而分配给计算机的值 ...

  7. [Android应用开发] 03.网络编程

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  8. python网络编程-socket编程

     一.服务端和客户端 BS架构 (腾讯通软件:server+client) CS架构 (web网站) C/S架构与socket的关系: 我们学习socket就是为了完成C/S架构的开发 二.OSI七层 ...

  9. Python全栈【Socket网络编程】

    Python全栈[socket网络编程] 本章内容: Socket 基于TCP的套接字 基于UDP的套接字 TCP粘包 SocketServer 模块(ThreadingTCPServer源码剖析) ...

随机推荐

  1. 一文详解|Go 分布式链路追踪实现原理

    在分布式.微服务架构下,应用一个请求往往贯穿多个分布式服务,这给应用的故障排查.性能优化带来新的挑战.分布式链路追踪作为解决分布式应用可观测问题的重要技术,愈发成为分布式应用不可缺少的基础设施.本文将 ...

  2. JavaScript知识梳理

    JS内功修炼 专业术语 类,封装,继承, 专业术语 babel 块级作用域 函数 扩展对象的功能性 解构 set和map js的类 改进的数组功能 Promise与异步编程 代理和反射 用模块封装代码 ...

  3. 基于脑波眼电-语音-APP控制的多功能智能轮椅

    前言:这个项目是在2016-2017完成的,做的很浅显,贴出来与大家分享,希望能有帮助. 摘要 本项目主要是针对脑电信号控制的智能轮椅的设计,脑电控制是智能医疗领域的重要研究方向,旨在帮助行动不便但智 ...

  4. 迭代器的实现原理和增强for循环

    Iterator遍历集合--工作原理 在调用Iterator的next方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位, 指向第 ...

  5. 如何验收安卓PCBA主板的质量和性能

    . 版本:v0.1 作者:河东西望 日期:2022-7-15 . 目录 1 有哪些情况需要验收? 2 有哪些验收测试? 2.1 主板测试 2.2 工程测试 2.3 性能测试 2.4 压力测试 2.5 ...

  6. 剑指offer——day-1

    今天开始记录一下剑指offer的题目训练,提升一下自己的编程能力吧 题目一: 用两个栈实现一个队列.队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列 ...

  7. JAVA定时任务原理入门

    本文适用语言:java 序章:定时任务实现方式 当下,java编码过程中,实现定时任务的方式主要以以下两种为主 spring框架的@Scheduled quzrtz框架 网络上关于这两种框架的实践和配 ...

  8. 【Java线程池】 java.util.concurrent.ThreadPoolExecutor 分析

    线程池概述 线程池,是指管理一组同构工作线程的资源池. 线程池在工作队列(Work Queue)中保存了所有等待执行的任务.工作者线程(Work Thread)会从工作队列中获取一个任务并执行,然后返 ...

  9. ShadeRec类定义

    这个类主要是用于记录碰撞数据的类,书中已经说的很清楚了.这个类之后会慢慢扩展,会在本随笔中扩展,先定义简单的,方便编译看看效果. 类声明(World是之后主程序中的类,最后测试时再实现): #ifnd ...

  10. java-分支重载以及构造方法

    1:方法的签名: 方法名+参数列表就是一个方法的签名 2.方法的重载(Overload): 1)发生在同一个类中,方法名称相同,参数列表不同 2)编译器在编译时会根据方法的签名自动绑定方法 3.构造方 ...