【Java】网络编程,JUnit单元测试,设计模式(一)

简介: 【Java】网络编程,JUnit单元测试,设计模式

day13-网络编程


主要内容如下


  • 网络编程
  • TCP通信
  • Junit单元测试
  • 单例设计模式
  • 多例设计模式
  • 工厂设计模式

1 网络编程


1.1 软件架构


  • C/S结构 :全称为Client/Server结构,是指客户端和服务器结构。常见程序有QQ、迅雷等软件
  • B/S结构 :全称为Browser/Server结构,是指浏览器和服务器结构。常见浏览器有谷歌、火狐等
  • 两种架构各有优势,但是都离不开网络的支持。网络编程 , 就是在一定的协议下,实现两台计算机的通信的程序

1.2 什么是网络编程


  • 在网络通信协议下,不同计算机上运行的程序,可以进行数据传输

1.3 网络编程三要素


  • IP地址 : 设备在网络中的地址,是唯一的标识。
  • 端口 : 设备在网络中的地址,是唯一的标识。
  • 数据在网络中传输的规则,常见的协议有UDP协议和TCP协议。

1.4 IP地址


  • IP:全称”互联网协议地址”,也称IP地址。是分配给上网设备的数字标签。常见的IP分类为:ipv4和ipv6
    简单来说 : 就是设备在网络中的唯一标识 , 想要连接哪一台电脑 , 就找到此电脑在网络中的ip地址
  • IP地址常见分类 : ipv4和ipv6
  • 常用命令:
  • ipconfig:查看本机IP地址
  • IP地址:检查网络是否连通
  • 特殊IP地址:
  • 127.0.0.1:是回送地址也称本地回环地址,可以代表本机的IP地址,一般用来测试使用
  • 为了方便我们对IP地址的获取和操作,Java提供了一个类InetAddress 供我们使用
    InetAddress:此类表示Internet协议(IP)地址
static InetAddress getByName(String host) 在给定主机名的情况下确定主机的 IP 地址
String getHostName() 获取此 IP 地址的主机名
String getHostAddress() 返回 IP 地址字符串(以文本表现形式)。

1.5 端口


  • 端口:应用程序在设备中唯一的标识。
  • 端口号:应用程序的唯一标识方式 , 用两个字节表示的整数,它的取值范围是0~65535。
    其中0~1023之间的端口号用于一些知名的网络服务或者应用。
  • 我们自己使用1024以上的端口号就可以了。
  • 注意:一个端口号只能被一个应用程序使用。

1.6 通信协议


  • 协议:计算机网络中,连接和通信的规则被称为网络通信协议
  • UDP协议
  • 用户数据报协议(User Datagram Protocol)
  • UDP是面向无连接通信协议。
  • 速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据。
  • TCP协议
  • 传输控制协议 (Transmission Control Protocol)
  • TCP协议是面向连接的通信协议。
  • 速度慢,没有大小限制,数据安全

2 TCP通信


2.1 TCP发送数据


package com.itheima.tcp_demo.demo1;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
/*
    客户端 :
    发送数据的步骤
        1 创建客户端的Socket对象 : Socket(String host, int port) 与指定服务端连接
            参数说明:
            host 表示服务器端的主机名,也可以是服务器端的IP地址,只不过是String类型的
            port 表示服务器端的端口
        2 通获Socket对象取网络中的输出流,写数据
            OutputStream getOutputStream()
        3 释放资源
            void close()
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        // 创建客户端的Socket对象(Socket) 与指定服务端连接
        Socket socket = new Socket("127.0.0.1", 10010);
        // 通获Socket对象取网络中的输出流,写数据
        OutputStream os = socket.getOutputStream();
        os.write("hello".getBytes());
        // while(true){}
        // 释放资源
        os.close();
        socket.close();
    }
}

2.2 TCP接收数据


package com.itheima.tcp_demo.demo1;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/*
     服务端接收数据 :
    1 创建服务器端的Socket对象 : ServerSocket类
        ServerSocket(int port)  : 构造方法需要绑定一个端口号 , port就是端口号
    2 监听客户端连接,并接受连接,返回一个Socket对象
        Socket accept() : 该方法会一直阻塞直到建立连接
    3 获取网络中的输入流,用来读取客户端发送过来的数据
        InputStream getInputStream()
    4 释放资源 : 服务端一般不会关闭
        void close()
 */
public class ServerDemo {
    public static void main(String[] args) throws IOException {
//        1 创建服务器端的Socket对象 : ServerSocket类
//        ServerSocket(int port)  : 构造方法需要绑定一个端口号 , port就是端口号
        ServerSocket serverSocket = new ServerSocket(10010);
//        2 监听客户端连接,并接受连接,返回一个Socket对象
//        Socket accept() : 该方法会一直阻塞直到建立连接
        Socket socket = serverSocket.accept();
//
//        3 获取网络中的输入流,用来读取客户端发送过来的数据
//        InputStream getInputStream()
        InputStream is = socket.getInputStream();
        int by;
        System.out.println("read方法执行前");
        while ((by = is.read()) != -1) {
            System.out.print((char) by);
        }
        System.out.println("read方法执行后");
    }
}

2.3 TCP练习1


package com.itheima.tcp_demo.test1;
import java.io.*;
import java.net.Socket;
/*
    客户端 :
    发送数据的步骤
        1 创建客户端的Socket对象 : Socket(String host, int port) 与指定服务端连接
            参数说明:
            host 表示服务器端的主机名,也可以是服务器端的IP地址,只不过是String类型的
            port 表示服务器端的端口
        2 通获Socket对象取网络中的输出流,写数据
            OutputStream getOutputStream​()
        3 释放资源
            void close​()
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        // 创建客户端的Socket对象(Socket) 与指定服务端连接
        Socket socket = new Socket("127.0.0.1", 10010);
        // 通获Socket对象取网络中的输出流,写数据
        OutputStream os = socket.getOutputStream();
        os.write("hello".getBytes());
        // 像服务端写入结束标记
        socket.shutdownOutput();
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line = br.readLine();
        System.out.println(line);
        // 释放资源
        br.close();
        os.close();
        socket.close();
    }
}
package com.itheima.tcp_demo.test1;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/*
     服务端接收数据 :
    1 创建服务器端的Socket对象 : ServerSocket类
        ServerSocket​(int port)  : 构造方法需要绑定一个端口号 , port就是端口号
    2 监听客户端连接,并接受连接,返回一个Socket对象
        Socket accept​() : 该方法会一直阻塞直到建立连接
    3 获取网络中的输入流,用来读取客户端发送过来的数据
        InputStream getInputStream​()
    4 释放资源 : 服务端一般不会关闭
        void close​()
 */
public class ServerDemo {
    public static void main(String[] args) throws IOException {
//        1 创建服务器端的Socket对象 : ServerSocket类
//        ServerSocket​(int port)  : 构造方法需要绑定一个端口号 , port就是端口号
        ServerSocket serverSocket = new ServerSocket(10010);
//        2 监听客户端连接,并接受连接,返回一个Socket对象
//        Socket accept​() : 该方法会一直阻塞直到建立连接
        Socket socket = serverSocket.accept();
//
//        3 获取网络中的输入流,用来读取客户端发送过来的数据
//        InputStream getInputStream​()
        InputStream is = socket.getInputStream();
        int by;
        while ((by = is.read()) != -1) {
            System.out.print((char) by);
        }
        BufferedWriter bos = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bos.write("你谁啊");
        bos.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}

2.4 TCP练习2


package com.itheima.tcp_demo.test2;
import java.io.*;
import java.net.Socket;
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        // 创建客户端Socket对象
        Socket socket = new Socket("127.0.0.1", 10086);
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\传智播客\\安装包\\好看的图片\\liqin.jpg"));
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        int by;
        while ((by = bis.read()) != -1) {// 从本地中读一个字节
            bos.write(by);// 往服务器写一个字节
            bos.flush();
        }
        // 写结束标记
        socket.shutdownOutput();
        // 把网络中的字节输入流 , 封装成高效的字符输入流
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//        String line;
//        while ((line = br.readLine()) != null) {
//            System.out.println(line);
//        }
        String msg = br.readLine();// 读到换行才叫读到一行, 所以必须写服务器必须写newLine
        System.out.println(msg);
        // 释放资源
        bis.close();
        socket.close();
    }
}
package com.itheima.tcp_demo.test2;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        // 创建服务端的连接对象
        ServerSocket serverSocket = new ServerSocket(10086);
        Socket socket = null;
        BufferedInputStream bis = null;
        BufferedWriter socketBw = null;
        while (true) {
            // 获取Socket对象
            socket = serverSocket.accept();
            // 获取网络中的字节输入流  在封装成高效的字节输入流对象
            bis = new BufferedInputStream(socket.getInputStream());
            // 创建本地的字节输出流 , 封装成高效的字节输出流
            BufferedOutputStream bw = new BufferedOutputStream(new FileOutputStream("day13_demo\\图片\\a.jpg"));
            int by;
            while ((by = bis.read()) != -1) {
                bw.write(by);
                bw.flush();
            }
            //关闭本地流
            bw.close();
            // 获取网络中的字节输出流 , 封装成高效的字符输出流
            socketBw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            socketBw.write("谢谢你");
            socketBw.newLine();// 必须有换行 , 因为readLine读到换行结束
            socketBw.flush();
        }
        // 释放资源
//        socketBw.close();
//        bis.close();
//        socket.close();
//        serverSocket.close();
    }
}

2.5 TCP练习3


package com.itheima.tcp_demo.test3;
import java.io.*;
import java.net.Socket;
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        // 创建客户端Socket对象
        Socket socket = new Socket("127.0.0.1", 10086);
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\传智播客\\安装包\\好看的图片\\liqin.jpg"));
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        int by;
        while ((by = bis.read()) != -1) {// 从本地中读一个字节
            bos.write(by);// 往服务器写一个字节
            bos.flush();
        }
        // 写结束标记
        socket.shutdownOutput();
        // 把网络中的字节输入流 , 封装成高效的字符输入流
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//        String line;
//        while ((line = br.readLine()) != null) {
//            System.out.println(line);
//        }
        String msg = br.readLine();// 读到换行才叫读到一行, 所以必须写服务器必须写newLine
        System.out.println(msg);
        // 释放资源
        bis.close();
        socket.close();
    }
}
package com.itheima.tcp_demo.test3;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ServerDemo {
    public static void main(String[] args) throws IOException {
        // 创建服务端的连接对象
        ServerSocket serverSocket = new ServerSocket(10086);
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        while (true) {
            // 获取Socket对象
            Socket socket = serverSocket.accept();
            executorService.submit(new ServerThread(socket));
        }
        // 释放资源
//        socketBw.close();
//        bis.close();
//        socket.close();
//        serverSocket.close();
    }
}
package com.itheima.tcp_demo.test3;
import javax.management.relation.RoleUnresolved;
import java.io.*;
import java.net.Socket;
import java.util.UUID;
public class ServerThread implements Runnable {
    Socket socket = null;
    BufferedOutputStream bw = null;
    public ServerThread(Socket socket) {
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            // 获取网络中的字节输入流  在封装成高效的字节输入流对象
            BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
            // 创建本地的字节输出流 , 封装成高效的字节输出流
            bw = new BufferedOutputStream(new FileOutputStream("day13_demo\\图片\\" + UUID.randomUUID() + ".jpg"));
            int by;
            while ((by = bis.read()) != -1) {
                bw.write(by);
                bw.flush();
            }
            // 获取网络中的字节输出流 , 封装成高效的字符输出流
            BufferedWriter socketBw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            socketBw.write("谢谢你");
            socketBw.newLine();// 必须有换行 , 因为readLine读到换行结束
            socketBw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭本地流
            try {
                bw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3 Junit单元测试


3.1 Junit4单元测试概述


  • 单元测试就是编写测试代码,可以准确、快速地保证程序的正确性,Junit是Java单元测试的框架。
  • JUnit4可以通过注解的方式来标记方法 , 让方法存某种意义 ,常见的注解有:
  • @BeforeClass 全局只会执行一次,而且是第一个运行(标记的方法需要是一个静态无参无返回值方法)
  • @Before 在测试方法运行之前运行(非静态无参无返回值方法)
  • **@Test 测试方法(此方法必须是非静态无参无返回值方法), 主要用于测试的方法 **
  • @After 在测试方法运行之后运行(非静态无参无返回值方法)
  • @AfterClass 全局只会执行一次,而且是最后一个运行(标记的方法需要是一个静态无参无返回值方法)
  • @Ignore 忽略此方法

3.2 Junit的基本使用


  • 已知存在需要测试的类Calculator ,这是一个能够简单实现加减乘除、平方、开方的计算器类,然后对这些功能进行单元测试。
// 计算器类
public class Calculator {
    // 静态变量,用于存储运行结果
    private static int result; // 20
    // 加法运算
    public void add(int n) {
        result = result + n;
    }
    // 减法运算
    public void subtract(int n) {
        // Bug: 正确的应该是 result = result - n
        result = result - 1;  
    }
    // 乘法运算
    public void multiply(int n) {
        // 此方法尚未写好
    }         
    // 除法运算
    public void divide(int n) {
        result = result / n;
    }
    // 平方运算
    public void square(int n) {
        result = n * n;
    }
    // 平方根运算
    public void squareRoot(int n) {
        // Bug : 死循环
        for (; ;) ;            
    }
    // 将结果清零
    public void clear() {     
        result = 0;
    }
    // 返回运算结果
    public int getResult(){
        return result;
    }
}

引入Junit4的jar包到模块中

第一步 : 在模块中新建文件夹lib,拷贝今天资料中junit4的jar包到模块中

  • 第二步 : 选中jar文件 , 右键选择 Add as Library
  • 生成Junit测试框架
  • 使用IDEA能够直接给需要测试的类生成测试框架,如下:
  • 选中本类任何位置右键选择 Generate(Alt+Insert)/ go to 选项 , 选择Test…
  • 选择需要进行测试的方法
  • 在上一步OK后系统会自动生成一个新类CalculatorTest,里面包含一些空的测试用例。
限时测试

对于那些逻辑很复杂,循环嵌套比较深的程序,很有可能出现死循环,因此一定要采取一些预防措施。限时测试是一个很好的解决方案。我们给这些测试函数设定一个执行时间,超过了这个时间,他们就会被系统强行终止,并且系统还会向你汇报该函数结束的原因是因为超时,这样你就可以发现这些Bug了。要实现这一功能,只需要给@Test标注加一个参数即可,代码如下:

被测方法:

public void squareRoot(int n) {
    //Bug : 死循环
    for (; ; ) ;            
}

测试方法:
@Test(timeout = 1000)
// Timeout参数表明了你要设定的时间,单位为毫秒,因此1000就代表1秒。
public void squareRoot() {
    calculator.squareRoot(4);
    assertEquals(2 , calculator.getResult());
}


相关文章
|
6月前
|
算法 IDE Java
Java 项目实战之实际代码实现与测试调试全过程详解
本文详细讲解了Java项目的实战开发流程,涵盖项目创建、代码实现(如计算器与汉诺塔问题)、单元测试(使用JUnit)及调试技巧(如断点调试与异常排查),帮助开发者掌握从编码到测试调试的完整技能,提升Java开发实战能力。
605 0
|
8月前
|
人工智能 Java 测试技术
Spring Boot 集成 JUnit 单元测试
本文介绍了在Spring Boot中使用JUnit 5进行单元测试的常用方法与技巧,包括添加依赖、编写测试类、使用@SpringBootTest参数、自动装配测试模块(如JSON、MVC、WebFlux、JDBC等),以及@MockBean和@SpyBean的应用。内容实用,适合Java开发者参考学习。
960 0
|
4月前
|
Java 测试技术 数据库连接
【SpringBoot(四)】还不懂文件上传?JUnit使用?本文带你了解SpringBoot的文件上传、异常处理、组件注入等知识!并且带你领悟JUnit单元测试的使用!
Spring专栏第四章,本文带你上手 SpringBoot 的文件上传、异常处理、组件注入等功能 并且为你演示Junit5的基础上手体验
999 3
|
10月前
|
测试技术
Fast网络速度测试工具
Fast是由Netflix提供的网络速度测试工具,可快速测量用户的下载、上传速度及延迟。其全球可用、无广告干扰,并支持多种设备。测试自动进行,结果以Mbps显示。此外,用户可通过“Show more info”查看上传速度和延迟(含缓冲膨胀)。Fast以其简单快捷的特点,帮助用户了解网络性能并解决潜在问题,是评估网速的理想选择。
1229 0
Fast网络速度测试工具
|
11月前
|
缓存 监控 负载均衡
如何提升 API 性能:来自 Java 和测试开发者的优化建议
本文探讨了如何优化API响应时间,提升用户体验。通过缓存(如Redis/Memcached)、减少数据负载(REST过滤字段或GraphQL精确请求)、负载均衡(Nginx/AWS等工具)、数据压缩(Gzip/Brotli)、限流节流、监控性能(Apipost/New Relic等工具)、升级基础设施、减少第三方依赖、优化数据库查询及采用异步处理等方式,可显著提高API速度。快速响应的API不仅让用户满意,还能增强应用整体性能。
|
7月前
|
安全 Java 测试技术
Java 项目实战中现代技术栈下代码实现与测试调试的完整流程
本文介绍基于Java 17和Spring技术栈的现代化项目开发实践。项目采用Gradle构建工具,实现模块化DDD分层架构,结合Spring WebFlux开发响应式API,并应用Record、Sealed Class等新特性。测试策略涵盖JUnit单元测试和Testcontainers集成测试,通过JFR和OpenTelemetry实现性能监控。部署阶段采用Docker容器化和Kubernetes编排,同时展示异步处理和反应式编程的性能优化。整套方案体现了现代Java开发的最佳实践,包括代码实现、测试调试
253 0
|
7月前
|
人工智能 Java 测试技术
Java or Python?测试开发工程师如何选择合适的编程语言?
测试工程师如何选择编程语言?Java 还是 Python?多位资深专家分享建议:Python 入门简单、开发效率高,适合新手及自动化测试;Java 生态成熟,适合大型项目和平台开发。建议结合公司技术栈、个人基础及发展方向选择。长远来看,两者兼通更佳,同时关注 Go 等新兴语言。快速学习与实践才是关键。
|
数据库连接 Go 数据库
Go语言中的错误注入与防御编程。错误注入通过模拟网络故障、数据库错误等,测试系统稳定性
本文探讨了Go语言中的错误注入与防御编程。错误注入通过模拟网络故障、数据库错误等,测试系统稳定性;防御编程则强调在编码时考虑各种错误情况,确保程序健壮性。文章详细介绍了这两种技术在Go语言中的实现方法及其重要性,旨在提升软件质量和可靠性。
247 1
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
1977 1
|
Java 测试技术 Maven
Java一分钟之-PowerMock:静态方法与私有方法测试
通过本文的详细介绍,您可以使用PowerMock轻松地测试Java代码中的静态方法和私有方法。PowerMock通过扩展Mockito,提供了强大的功能,帮助开发者在复杂的测试场景中保持高效和准确的单元测试。希望本文对您的Java单元测试有所帮助。
2202 2