概述
Java进阶之Junit单元测试&网络编程
- 一、Junit单元测试
- 1.1 单元测试基本使用
- 1.1.1 @Test注解
- 1.1.2 单元测试其他注解
- 1.2 断言
- 二、网络编程
- 2.1 IP地址
- 2.2 端口号
- 2.3 协议
- 2.4 客户端和服务器
- 2.5 InetAddress
- 2.6 TCP协议
- 2.6.1 TCP协议中IO流
- 2.6.2 TCP通信客户端
- 2.6.3 TCP协议服务端
- 2.6.4 TCP的上传案例
- 2.6.4.1 客户端上传
- 2.6.4.2 服务端接收
- 2.6.4.3 服务端接收-死循环版本
- 2.6.4.4 服务端接收-多线程版本
- 2.6.5 模拟B/S案例
一、Junit单元测试
1.1 单元测试基本使用
junit叫做单元测试,单元测试用来代替程序中的main方法,程序可以直接从单元测试方法开始运行。
Junit的使用步骤:
- 下载对应的jar包
- 在模块下面创建一个lib文件夹,把jar包放进去
- 右键点击jar包,选择Add as Library
1.1.1 @Test注解
如果在一个方法上加上@Test注解,那么这个方法就是一个单元测试方法了,程序可以直接从该方法开始运行。
方法的要求:
- 方法一般以test开头(软性规定)
- public修饰,没有参数,没有返回值(硬性规定)
如何运行:
- 选中方法,右键run
- 选中类,右键run【会执行该类中所有的单元测试方法】
public class Demo01JUnit {
@Test
public void testFunction() {
System.out.println("testFunction执行了");
}
@Test
public void testMethod() {
System.out.println("testMethod执行了");
}
}
1.1.2 单元测试其他注解
Junit4:
Before
使用该注解修饰的方法,会在每次单元测试方法执行之前执行After
使用该注解修饰的方法,会在每次单元测试方法执行之后执行BeforeClass
使用该注解修饰的方法,会在所有方法执行之前执行,只执行一次AfterClass
使用该注解修饰的方法,会在所有方法执行之后执行,只执行一次
注意:使用BeforeClass
和AfterClass
修饰的方法必须加静态。
Junit5:
@BeforeEach
使用该注解修饰的方法,会在每次单元测试方法执行之前执行@AfterEach
使用该注解修饰的方法,会在每次单元测试方法执行之后执行@BeforeAll
使用该注解修饰的方法,会在所有方法执行之前执行,只执行一次@AfterAll
使用该注解修饰的方法,会在所有方法执行之后执行,只执行一次
1.2 断言
断言:可以判断结果是否是预期值,如果是,程序正常,如果不是,程序会崩溃
Assert.assertEquals(期望结果 , 实际结果)
判断结果是否是预期值,如果是,程序正常,如果不是,程序会崩溃
public class Demo03JUnit {
@Test
public void testMethod() {
//求两个变量的和
int a = 10;
int b = 20;
int sum = a + b;
//使用断言判断这个结果是否是30
Assert.assertEquals(50, sum);
}
}
二、网络编程
不同计算机上的程序,在网络的互连下完成数据的交换,就是网络编程。
2.1 IP地址
2.2 端口号
2.3 协议
数据在网络中传输的规则,常见的协议有UDP协议和TCP协议。
UDP协议:
- UDP是无连接通信协议,在数据传输时,数据的发送端和接收端不需要建立连接
通常应用于广播或者音频、视频的传输
TCP协议:
- TCP是面向连接的通信协议, 在数据传输时,数据的发送端和接收端需要先确认连接,再去收发数据,提供了计算机之间可靠安全的数据传输,通常应用于文件上传 文件下载 浏览网页等
2.4 客户端和服务器
2.5 InetAddress
InetAddress
表示IP地址
方法:
static InetAddress getByName(String host)
:获取目标机器的IP地址对象,参数是IP地址或者主机名String getHostName()
:获取此IP地址的主机名String getHostAddress()
:返回文本显示中的IP地址字符串
public class Demo05Test {
public static void main(String[] args) throws UnknownHostException {
InetAddress inetAddress = InetAddress.getByName("192.168.128.139");
System.out.println(inetAddress.getHostName()); //192.168.128.139
System.out.println(inetAddress.getHostAddress());//192.168.128.139
}
}
2.6 TCP协议
2.6.1 TCP协议中IO流
2.6.2 TCP通信客户端
TCP的两端分别是客户端和服务器。
在Java中有一个类叫做Socket,这个类就表示TCP的客户端程序。
Socket构造方法:
Socket(String host, int port)
:参数host表示目标服务器的ip地址,参数port表示目标服务器程序的端口号
Socket其他方法:
InputStream getInputStream()
:获取一个输入流,用来接收数据OutputStream getOutputStream()
:获取一个输出流,用来发送数据void close()
:释放资源
TCP客户端的实现步骤:
- 创建客户端Socket对象,指定要连接的服务器
- 通过Socket调用getOutputStream获取输出流
- 使用获取到的输出流给服务器发送数据
- 通过Socket调用getInputStream获取输入流
- 使用获取的输入流接收服务器发送过来的数据
- 释放资源
注意:通过Socket获取到的流不需要手动关闭,只需要关闭Socket即可。
public class Demo01Client {
public static void main(String[] args) throws IOException {
//1. 创建客户端Socket对象,指定要连接的服务器。
//创建客户端Socket对象时,会主动连接服务器,如果连接不成功,就会报错(三次握手)
Socket socket = new Socket("127.0.0.1", 9527);
//2. 通过Socket调用getOutputStream获取输出流。
OutputStream out = socket.getOutputStream();
//3. 使用获取到的输出流给服务器发送(写)数据。
out.write("你好".getBytes());
//4. 通过Socket调用getInputStream获取输入流。
InputStream in = socket.getInputStream();
//5. 使用获取的输入流接收(读取)服务器发送过来的数据
byte[] bArr = new byte[1024];
int len = in.read(bArr);
System.out.println(new String(bArr, 0, len));
//6. 释放资源
socket.close();
}
}
2.6.3 TCP协议服务端
在Java中有一个类叫做ServerSocket,这个类表示TCP的服务器端。
ServerSocket构造方法:
ServerSocket(int port)
:参数要传递端口号,该端口号表示本服务器的端口号
ServerSocket其他方法:
Socket accept()
:监听并获取客户端Socket(请求)
TCP服务器的实现步骤:
- 创建服务器ServerSocket对象,指定自己的端口号
- 通过ServerSocket调用accept方法,监听并获取客户端Socket
- 通过Socket调用getInputStream,获取输入流(该输入流的数据源是客户端)
- 通过输入流接收客户端发送过来的数据
- 通过Socket调用getOutputStream,获取输出流(该输出流的目的地是客户端)
- 通过输出流给客户端发送数据
- 释放资源
public class Demo02Server {
public static void main(String[] args) throws IOException {
//1. 创建服务器ServerSocket对象,指定自己的端口号。
ServerSocket serverSocket = new ServerSocket(9527);
//2. 通过ServerSocket调用accept方法,监听并获取客户端Socket
Socket socket = serverSocket.accept();
//3. 通过Socket调用getInputStream,获取输入流(该输入流的数据源是客户端)
InputStream in = socket.getInputStream();
//4. 通过输入流接收(读取)客户端发送过来的数据。
byte[] bArr = new byte[1024];
int len = in.read(bArr);
System.out.println(new String(bArr, 0, len));
//5. 通过Socket调用getOutputStream,获取输出流(该输出流的目的地是客户端)
OutputStream out = socket.getOutputStream();
//6. 通过输出流给客户端发送数据。
out.write("收到".getBytes());
//7. 释放资源
socket.close();
serverSocket.close();
}
}
2.6.4 TCP的上传案例
2.6.4.1 客户端上传
对于客户端来说,要做的事情是读取自己电脑文件中的字节,然后再写给服务器。然后接收服务器的回复(上传成功)。
客户端的实现步骤:
- 创建客户端Socket对象
- 创建字节输入流,用来读取客户端中的文件
- 通过Socket对象获取输出流,用来给服务器发送数据
- 开始读写,一次读写一个字节数组,每从客户端文件中读取一次,就将读取到的数据发给服务器
- 释放资源
- 通过Socket对象获取输入流,用来从服务器中读取数据
- 通过输入流调用read方法,接收数据
- 释放资源
public class Demo01Client {
public static void main(String[] args) throws IOException {
//1. 创建客户端Socket对象。
Socket socket = new Socket("127.0.0.1", 9527);
//2. 创建字节输入流,用来读取客户端中的文件
InputStream is = new FileInputStream("d:\client\aa.jpg");
//3. 通过Socket对象获取输出流,用来给服务器发送数据
OutputStream out = socket.getOutputStream();
//4. 开始读写,一次读写一个字节数组,每从客户端文件中读取一次,就将读取到的数据发给服务器
byte[] bArr = new byte[1024];
int len;
while ((len = is.read(bArr)) != -1) {
//条件成立表示读取到了数据,那么就将数据发送给服务器
out.write(bArr, 0, len);
}
//让客户端给服务器一个通知,告诉服务器,以后再也不会给你写数据了
socket.shutdownOutput();
//5. 释放资源。
is.close();
//6. 通过Socket对象获取输入流,用来从服务器中读取数据。
InputStream in = socket.getInputStream();
//7. 通过输入流调用read方法,接受数据。
len = in.read(bArr);
System.out.println(new String(bArr, 0, len));
//8. 释放资源。
socket.close();
}
}
2.6.4.2 服务端接收
对于服务器来说,要做的事情是接收客户端发来的字节,然后写到自己电脑的文件中,然后给客户端回复(上传成功)。
上传案例服务器端的实现步骤:
- 创建服务器ServerSocket对象
- 调用accept方法,监听客户端的请求
- 通过Socket对象获取输入流,用来从客户端读取数据
- 创建字节输出流,用来向服务器自己电脑写数据
- 开始读写,每读取一次,就将读取到的数据写到服务器自己电脑的文件中
- 释放资源
- 通过Socket对象获取输出流,用来给客户端发送数据
- 通过输出流调用write方法,发送数据
- 释放资源
public class Demo02Server {
public static void main(String[] args) throws IOException {
//1. 创建服务器ServerSocket对象
ServerSocket serverSocket = new ServerSocket(9527);
//2. 调用accept方法,监听客户端的请求
Socket socket = serverSocket.accept();
//3. 通过Socket对象获取输入流,用来从客户端读取数据
InputStream in = socket.getInputStream();
//4. 创建字节输出流,用来向服务器自己电脑写数据。
//OutputStream os = new FileOutputStream("d:\server\aa.jpg");
//OutputStream os = new FileOutputStream("d:\server\" + System.currentTimeMillis() + ".jpg");
//在Java中有一个类叫做UUID,里面的静态方法randomUUID可以获取一个随机的,不重复的字符序列
OutputStream os = new FileOutputStream("d:\server\" + UUID.randomUUID().toString() + ".jpg");
//5. 开始读写,每读取一次,就将读取到的数据写到服务器自己电脑的文件中
byte[] bArr = new byte[1024];
int len;
while ((len = in.read(bArr)) != -1) {
//如果条件成立表示读取到了数据,就将读取到的数据写到服务器自己电脑的文件中
os.write(bArr, 0, len);
}
//6. 释放资源
os.close();
//7. 通过Socket对象获取输出流,用来给客户端发送数据
OutputStream out = socket.getOutputStream();
//8. 通过输出流调用write方法,发送数据。
out.write("上传成功".getBytes());
//9. 释放资源。
socket.close();
serverSocket.close();
}
}
2.6.4.3 服务端接收-死循环版本
上面的服务器在客户端上传一次之后就停止了,真正的服务器是不能停的。
如果想要让服务器不能停,让服务器一直给客户端提供上传的功能,那么可以使用死循环。
public class Demo03DeadLoopServer {
public static void main(String[] args) throws IOException {
//1. 创建服务器ServerSocket对象
ServerSocket serverSocket = new ServerSocket(9527);
//要在死循环中监听客户端请求以及完成上传任务
while(true) {
//2. 调用accept方法,监听客户端的请求。
Socket socket = serverSocket.accept();
//3. 通过Socket对象获取输入流,用来从客户端读取数据。
InputStream in = socket.getInputStream();
//4. 创建字节输出流,用来向服务器自己电脑写数据。
OutputStream os = new FileOutputStream("d:\server\" + UUID.randomUUID().toString() + ".jpg");
//5. 开始读写,每读取一次,就将读取到的数据写到服务器自己的电脑。
byte[] bArr = new byte[1024];
int len;
while ((len = in.read(bArr)) != -1) {
//如果条件成立表示读取到了数据,就将读取到的数据写到服务器自己电脑。
os.write(bArr, 0, len);
}
//6. 释放资源
os.close();
//7. 通过Socket对象获取输出流,用来给客户端发送数据。
OutputStream out = socket.getOutputStream();
//8. 通过输出流调用write方法,发送数据。
out.write("上传成功".getBytes());
//9. 释放资源。
socket.close();
}
}
}
2.6.4.4 服务端接收-多线程版本
上面的上传服务器还有一些缺陷,如果有一个客户端上传了非常大的文件,服务器会一直给这个客户端执行上传任务,那么就无法监听其他客户端的请求了。
原因:
- 在程序中只有一个main线程,当程序启动时,main线程会执行,main线程会监听客户端的请求,如果有客户端来连接了,那么main线程还会给该客户端执行上传任务,如果上传文件非常大,那么main线程会一直执行该上传任务,那么就无法继续监听后面的客户端请求了
解决方式:
- 使用多线程,让main线程监听客户端的请求,如果有客户端来连接了,那么就新建一个线程执行上传任务,那么新线程执行上传任务的同时不会影响到main线程后面的执行,main线程可以继续向下执行,监听其他客户端的请求
public class Demo04ThreadServer {
public static void main(String[] args) throws IOException {
//1. 创建服务器ServerSocket对象
ServerSocket serverSocket = new ServerSocket(9527);
//要在死循环中监听客户端请求以及完成上传任务
while(true) {
//2. 调用accept方法,监听客户端的请求。
Socket socket = serverSocket.accept();
//新建一个线程,执行上传任务
new Thread(() -> {
try {
//3. 通过Socket对象获取输入流,用来从客户端读取数据。
InputStream in = socket.getInputStream();
//4. 创建字节输出流,用来向服务器自己电脑写数据。
OutputStream os = new FileOutputStream("d:\server\" + UUID.randomUUID().toString() + ".jpg");
//5. 开始读写,每读取一次,就将读取到的数据写到服务器自己的电脑。
byte[] bArr = new byte[1024];
int len;
while ((len = in.read(bArr)) != -1) {
//如果条件成立表示读取到了数据,就将读取到的数据写到服务器自己电脑。
os.write(bArr, 0, len);
}
//6. 释放资源
os.close();
//7. 通过Socket对象获取输出流,用来给客户端发送数据。
OutputStream out = socket.getOutputStream();
//8. 通过输出流调用write方法,发送数据。
out.write("上传成功".getBytes());
//9. 释放资源。
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
}
2.6.5 模拟B/S案例
浏览器也可以当做客户端去访问服务器。
如果浏览器当做客户端去访问服务器,那么这种结构的程序就是B/S结构的程序。
当浏览器去访问服务器时,服务器要给浏览器回复html文件的内容,回复的html文件的内容是什么,那么浏览器看到的内容就是什么。
public class Demo01Server {
public static void main(String[] args) throws IOException {
//创建服务器ServerSocket对象
ServerSocket serverSocket = new ServerSocket(10086);
//使用死循环一直监听客户端(浏览器)的请求,并给浏览器回复数据
while(true) {
//调用accept方法,监听客户端请求
Socket socket = serverSocket.accept();
//每监听到客户端(浏览器)的请求,就创建新的线程执行任务
new Thread(() -> {
try {
//当浏览器来访问服务器时,服务器要给浏览器回复数据,所以要获取一个输出流
OutputStream out = socket.getOutputStream();
//因为服务器要读取自己电脑中的html文件,所以要创建一个输入流
InputStream is = new FileInputStream("day12\index.html");
//由于http协议的限制,服务器回写给浏览器的前三行数据是固定的。
out.write("HTTP/1.1 200 OKrn".getBytes());//第一行
out.write("Content-Type=html/textrn".getBytes());//第二行
out.write("rn".getBytes());//第三行
//写完前三行数据后,那么再让服务器给浏览器回复html文件的内容
byte[] bArr = new byte[1024];
int len;
while ((len = is.read(bArr)) != -1) {
out.write(bArr, 0, len);
}
//释放资源
is.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
}
最后
以上就是飞快草莓为你收集整理的Java进阶之Junit单元测试&网络编程一、Junit单元测试二、网络编程的全部内容,希望文章能够帮你解决Java进阶之Junit单元测试&网络编程一、Junit单元测试二、网络编程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复