Java进阶14 TCP日志枚举

Java进阶14 TCP&日志&枚举

一、网络编程TCP

Java对基于TCP协议得网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信。

1、TCP协议发数据
1.1 构造方法

方法

说明

Socket(InetAddress address,int port)

创建流套接字并将其连接到指定IP指定端口号

Socket(String host,int port)

创建流套接字并将其连接到指定主机上的指定端口号

1.2 相关方法

方法

说明

InputStream getInputStream()

返回此套接字的输入流

OutputStream getOutputStream()

返回此套接字的输出流

1.3 代码实现
public class Client {
 ? ?public static void main(String[] args) throws IOException {
 ? ? ? ?//创建客户端的Socket对象(Socket)
 ? ? ? ?//Socket(String host, int port) 创建流套接字并将其连接到指定主机上的指定端口号
 ? ? ? ?Socket s = new Socket("127.0.0.1",10000);
?
 ? ? ? ?//获取输出流,写数据
 ? ? ? ?//OutputStream getOutputStream() 返回此套接字的输出流
 ? ? ? ?OutputStream os = s.getOutputStream();
 ? ? ? ?os.write("hello,tcp,我来了".getBytes());
?
 ? ? ? ?//释放资源
 ? ? ? ?os.close();
 ? ? ? ?s.close();
 ?  }
}
2、TCP协议收数据

Java为客户端提供了Socket类,为服务端提供了ServeSocket类

2.1 构造方法

方法

说明

ServerSocket(int port)

创建绑定到指定端口的服务器套接字

2.2 相关方法

方法

说明

Socket accept()

监听要连接到此的套接字并接受它

2.3 代码实现
public class Server {
 ? ?public static void main(String[] args) throws IOException {
 ? ? ? ?//创建服务器端的Socket对象(ServerSocket)
 ? ? ? ?//ServerSocket(int port) 创建绑定到指定端口的服务器套接字
 ? ? ? ?ServerSocket ss = new ServerSocket(10000);
?
 ? ? ? ?//Socket accept() 侦听要连接到此套接字并接受它
 ? ? ? ?Socket s = ss.accept();
?
 ? ? ? ?//获取输入流,读数据,并把数据显示在控制台
 ? ? ? ?InputStream is = s.getInputStream();
 ? ? ? ?byte[] bys = new byte[1024];
 ? ? ? ?int len = is.read(bys);
 ? ? ? ?String data = new String(bys,0,len);
 ? ? ? ?System.out.println("数据是:" + data);
?
 ? ? ? ?//释放资源
 ? ? ? ?s.close();
 ? ? ? ?ss.close();
 ?  }
}

注意事项:

  • accept方法是阻塞的,作用就是等待客户端连接

  • 客户端创建对象并连接服务器,此时是通过三次握手协议,保证跟服务器之间的连接

  • 针对客户端来讲,是往外写的,所以是输出流 针对服务器来讲,是往里读的,所以是输入流

  • read方法也是阻塞的

  • 客户端在关流的时候,还多了一个往服务器写结束标记的动作

  • 最后一步断开连接,通过四次挥手协议保证连接终止

3、三次握手和四次挥手
3.1 三次握手

3.2 四次挥手

4、TCP文件上传案例
  • 案例需求

    客户端:数据来自于本地文件,接收服务器反馈

    服务器:接收到的数据写入本地文件,给出反馈

  • 分析思路

    • 创建客户端对象,创建输入流对象指向文件,每读一次数据就给服务器输出一次数据,输出结束后使用shutdownOutput()方法告知服务端传输结束

    • 创建服务器对象,创建输出流对象指向文件,每接受一次数据就使用输出流输出到文件中,传输结束后,使用输出流给客户端反馈信息

    • 客户端接收服务端的回馈信息

  • 相关方法

    方法

    说明

    void shutdownInput()

    将此套接字的输入流放置在“流的末尾”

    void shutdownOutput()

    禁止用此套接字的输出流

  • 服务端优化思路

    • 服务端可以多次处理

      • 循环包裹while(true)

      • 使用UUID区分了重名文件,防止二次上传文件重名造成覆盖

    • 将服务器改进为多线程版本,满足多个客户端同时通信

    • 改为线程池

  • 代码实现

public class Client {
 ? ?public static void main(String[] args) throws IOException {
 ? ? ? ?//1、创建Socket对象指定ip和端口
 ? ? ? ?Socket socket = new Socket("192.168.11.251",8888);
 ? ? ? ?//2、获取传输数据的流对象(网络流)
 ? ? ? ?InputStream is = socket.getInputStream();
 ? ? ? ?OutputStream os = socket.getOutputStream();
 ? ? ? ?//3、将字节流转换为字符串(读写的内容有中文)
 ? ? ? ?BufferedReader br = new BufferedReader(new InputStreamReader(is));
 ? ? ? ?PrintStream ps = new PrintStream(os);
 ? ? ? ?File file = new File("D:\好哥哥.jpg");
 ? ? ? ?//4、写出文件名
 ? ? ? ?ps.println(file.getName());
 ? ? ? ?//5、读取服务端消息
 ? ? ? ?String state = br.readLine();
 ? ? ? ?if("ok".equals(state)){
 ? ? ? ? ? ?//6、上传文件(字节)
 ? ? ? ? ? ?//创建本地字节输入流关联要上传的文件
 ? ? ? ? ? ?FileInputStream fis = new FileInputStream(file);
 ? ? ? ? ? ?byte[] bys = new byte[1024];
 ? ? ? ? ? ?int len;
 ? ? ? ? ? ?while((len=fis.read(bys))!=-1){
 ? ? ? ? ? ? ? ?os.write(bys,0,len);
 ? ? ? ? ?  }
 ? ? ? ? ? ?//重点:写出结束标记给服务端
 ? ? ? ? ? ?socket.shutdownOutput();
 ? ? ? ? ? ?fis.close();
 ? ? ? ? ? ?//7、读取上传结果
 ? ? ? ? ? ?String result = br.readLine();
 ? ? ? ? ? ?System.out.println(result);
 ? ? ? ? ? ?//8、关流
 ? ? ? ? ? ?socket.close();
 ? ? ?  }
 ?  }
}

public class Server {
 ? ?public static void main(String[] args) throws IOException {
 ? ? ? ?//1、创建ServerSocket对象指定端口
 ? ? ? ?ServerSocket server = new ServerSocket(8888);
 ? ? ? ?System.out.println("服务端开启,等待客户端连接");
?
 ? ? ? ?ThreadPoolExecutor pool = new ThreadPoolExecutor(
 ? ? ? ? ? ? ? ?5,
 ? ? ? ? ? ? ? ?10,
 ? ? ? ? ? ? ? ?60,
 ? ? ? ? ? ? ? ?TimeUnit.SECONDS,
 ? ? ? ? ? ? ? ?new ArrayBlockingQueue<>(20),
 ? ? ? ? ? ? ? ?Executors.defaultThreadFactory(),
 ? ? ? ? ? ? ? ?new ThreadPoolExecutor.AbortPolicy()
 ? ? ?  );
?
 ? ? ? ?while (true) {
 ? ? ? ? ? ?//2、调用accept方法响应客户端的请求
 ? ? ? ? ? ?Socket socket = server.accept();
?
 ? ? ? ? ? ?//new Thread(new SubmitFileTask(socket)).start();
 ? ? ? ? ? ?pool.submit(new FileSubmitTask(socket));
 ? ? ?  }
 ?  }
}

public class FileSubmitTask implements Runnable{
 ? ?//为了拿到另一个类的数据,将其作为参数传进本类,在本类创建带参构造并接收该参数赋值给本类的成员变量,就拿到了
 ? ?private Socket socket;
 ? ?public FileSubmitTask(Socket socket) {
 ? ? ? ?this.socket=socket;
 ?  }
?
 ? ?@Override
 ? ?public void run() {
 ? ? ? ?try {
 ? ? ? ? ? ?//3、获取传输的输入流对象(网络流)
 ? ? ? ? ? ?InputStream is = socket.getInputStream();
 ? ? ? ? ? ?OutputStream os = socket.getOutputStream();
 ? ? ? ? ? ?//4、将字节流转换为字符串(读写的内容有中文)
 ? ? ? ? ? ?BufferedReader br = new BufferedReader(new InputStreamReader(is));
 ? ? ? ? ? ?PrintStream ps = new PrintStream(os);
 ? ? ? ? ? ?//5、读取客户端发送的文件名
 ? ? ? ? ? ?String fileName = br.readLine();
 ? ? ? ? ? ?//关联服务端的存储路径
 ? ? ? ? ? ?File update = new File("D:\itheima\Resource", UUID.randomUUID()+fileName);
 ? ? ? ? ? ?//6、写给客户端消息
 ? ? ? ? ? ?ps.println("ok");
 ? ? ? ? ? ?//7、创建本地字节输出流,关联存储路径
 ? ? ? ? ? ?FileOutputStream fos = new FileOutputStream(update);
 ? ? ? ? ? ?//8、IO读写
 ? ? ? ? ? ?byte[] bys = new byte[1024];
 ? ? ? ? ? ?int len;
 ? ? ? ? ? ?while((len = is.read(bys))!=-1){
 ? ? ? ? ? ? ? ?fos.write(bys,0,len);
 ? ? ? ? ?  }
 ? ? ? ? ? ?fos.close();
 ? ? ? ? ? ?//9、写出上传成功
 ? ? ? ? ? ?ps.println("上传成功!");
 ? ? ? ? ? ?//10、关流
 ? ? ? ? ? ?socket.close();
 ? ? ?  } catch (IOException e) {
 ? ? ? ? ? ?e.printStackTrace();
 ? ? ?  }
 ?  }
}

二、日志

程序中的日志可以用来记录程序运行过程中的信息,并可以进行永久存储。日志和输出语句的比较

输出语句

日志技术

输出位置

只能是控制台

可以将日志信息写入到文件或者数据库中

取消日志

需要修改代码,灵活性比较差

不需要修改代码,灵活性比较好

多线程

性能较差

性能较好

1、日志体系结构

  • 日志规范:一些接口,提供给日志的实现框架设计的标准

  • 日志框架:牛人或者第三方公司已经做好的日志记录实现代码,后来直接可以拿去使用

  • 因为对Commons Logging 的接口不满意,有人就搞了SLF4J;因为对Log4j的性能不满意,有人就搞了Logback

2、Logback快速入门
  • 官网: Logback Home

  • 三个技术模块

    模块名

    介绍

    locback-core

    该模块为其他两个模块提供基础代码,必须有。

    logback-classic

    完整实现了slf4j API的模块。

    logback-access

    logback-access 模块与 Tomcat 和 Jetty 等 Servlet 容器集成,以提供 HTTP 访问日志功能

2.1 操纵步骤
第一步:引入jar包

jar包本质来说就是压缩包,内部存储的都是别人已经写好的代码。在需要导包的项目模块下,和src平级的位置,创建lib目录,将需要的jar包都放进去,然后勾选Add as Library。导jar包只是目前的做法,后面会学maven来管理jar包,不用手动导入

第二步:导入配置文件

将日志的配置信息文件(logback.xml)复制到模块的src

  • 日志级别和配置文件详解

    通过通过logback.xml 中的标签可以设置输出位置和日志信息的详细格式。通常可以设置2个日志输出位置:一个是控制台、一个是系统文件中

第三步:获取日志对象使用
public class LogTest {
 ? ?public static void main(String[] args) {
 ? ? ? ?//获取记录日志对象
 ? ? ? ?Logger logger = LoggerFactory.getLogger("LogTest.class");
 ? ? ? ?//记录日志
 ? ? ? ?logger.info("记录了一条日志");
 ?  }
}

三、枚举

枚举是Java中的一种特殊类型,其作用是为了做信息的标志和信息的分类。枚举可以理解为一种多例设计模式,保证类的对象,在内存中只有固定的几个

1、定义格式

修饰符 enum 枚举类型{
//第一行都是罗列枚举类实例的名称
枚举项1,枚举项2,枚举项3;
}

enum Season{
 ? ?SPRING,SUMMER,AUTUMN,WINTER;
}
2、枚举的特点
  • 所有枚举类都是 Enum 的子类

  • 我们可以通过"枚举类名.枚举项名称"去访问指定的枚举项

  • 每一个枚举项其实就是该枚举的一个对象

  • 枚举也是类, 可以定义成员变量

  • 枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的,但是如果枚举类有其他的东西,这个分号就不能省略。建议不要省略

  • 枚举类可以有构造器,但必须是 private 的,它默认的也是 private 的。枚举项的用法比较特殊:枚举(“”);

  • 枚举类也可以有抽象方法,但是枚举项必须重写该方法

3、示例代码
public enum Season {
?
 ? ?SPRING("春"){
?
 ? ? ? ?//如果枚举类中有抽象方法
 ? ? ? ?//那么在枚举项中必须要全部重写
 ? ? ? ?@Override
 ? ? ? ?public void show() {
 ? ? ? ? ? ?System.out.println(this.name);
 ? ? ?  }
?
 ?  },
?
 ? ?SUMMER("夏"){
 ? ? ? ?@Override
 ? ? ? ?public void show() {
 ? ? ? ? ? ?System.out.println(this.name);
 ? ? ?  }
 ?  },
?
 ? ?AUTUMN("秋"){
 ? ? ? ?@Override
 ? ? ? ?public void show() {
 ? ? ? ? ? ?System.out.println(this.name);
 ? ? ?  }
 ?  },
?
 ? ?WINTER("冬"){
 ? ? ? ?@Override
 ? ? ? ?public void show() {
 ? ? ? ? ? ?System.out.println(this.name);
 ? ? ?  }
 ?  };
?
 ? ?public String name;
?
 ? ?//空参构造
 ? ?//private Season(){}
 ?
 ? ?//有参构造
 ? ?private Season(String name){
 ? ? ? ?this.name = name;
 ?  }
 ?
 ? ?//抽象方法
 ? ?public abstract void show();
}
?
public class EnumDemo {
 ? ?public static void main(String[] args) {
 ? ? ? ?//我们可以通过"枚举类名.枚举项名称"去访问指定的枚举项
 ? ? ? ?System.out.println(Season.SPRING);
 ? ? ? ?System.out.println(Season.SUMMER);
 ? ? ? ?System.out.println(Season.AUTUMN);
 ? ? ? ?System.out.println(Season.WINTER);
?
 ? ? ? ?//每一个枚举项其实就是该枚举的一个对象
 ? ? ? ?Season spring = Season.SPRING;
 ?  }
}
4、做信息标志方式(2种)
4.1 常量

虽然可以实现可读性,但是入参不受约束,代码相对不够严谨

4.2 枚举

代码可读性好,入参约束严谨,代码优雅,是最好的信息分类技术!建议使用!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/964732.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java三十天速成(java进阶篇)

Day 15 一、集合框架 1、集合框架图 2、数据结构&#xff1a; ①、逻辑结构&#xff1b; 在计算机科学中&#xff0c;逻辑结构是指数据元素之间的关系&#xff0c;它描述了数据元素之间的逻辑联系&#xff0c;而不是它们在计算机内存中的物理存储方式。逻辑结构可以分为以下…

专门记录台式电脑常见问题

1、蓝屏死机&#xff0c;检查内存硬盘和cpu 2、拆内存条&#xff0c;用橡皮擦金手指 3、放主板静电&#xff0c;扣主板电池 4、系统时间不正确&#xff0c;主板电池没电 5、开机键坏了 6、电脑主机的风扇转&#xff0c;正常通电运行&#xff0c;但显示器没信号。看键盘的num键&…

ubuntu22.40安装及配置静态ip解决重启后配置失效

遇到这种错误&#xff0c;断网安装即可&#xff01; 在Ubuntu中配置静态IP地址的步骤如下。根据你使用的Ubuntu版本&#xff08;如 Netplan 或传统的 ifupdown&#xff09;&#xff0c;配置方法有所不同。以下是基于 Netplan 的配置方法&#xff08;适用于Ubuntu 17.10及更高版…

北大AGI与具身智能评估新范式!Tong测试:基于动态具身物理和社会互动的评估标准

作者&#xff1a;Yujia Peng, Jiaheng Han, Zhenliang Zhang, Lifeng Fan, Tengyu Liu, Siyuan Qi, Xue Feng, Yuxi Ma, Yizhou Wang, Song-Chun Zhu 单位&#xff1a;北京通用人工智能研究院国家通用人工智能重点实验室&#xff0c;北京大学人工智能研究所&#xff0c;北京大…

DeePseek结合PS!批量处理图片的方法教程

​ ​ 今天我们来聊聊如何利用deepseek和Photoshop&#xff08;PS&#xff09;实现图片的批量处理。 传统上&#xff0c;批量修改图片尺寸、分辨率等任务往往需要编写脚本或手动处理&#xff0c;而现在有了AI的辅助&#xff0c;我们可以轻松生成PS脚本&#xff0c;实现自动化处…

OkHttpClient请求失败处理与网页下载成功实践

在现代的网络应用开发中&#xff0c;数据的获取和处理是核心任务之一。无论是从第三方API获取数据&#xff0c;还是从网页中提取内容&#xff0c;网络请求都是不可或缺的环节。在Java中&#xff0c;OkHttp是一个非常流行且功能强大的HTTP客户端库&#xff0c;它提供了简洁的API…

Idea ⽆ Maven 选项

Idea ⽆ Maven 选项 1. 在 Idea 项⽬上右键2. 选中 Maven 选项 如果在创建 Spring/Spring Boot 项⽬时&#xff0c;Idea 右侧没有 Maven 选项&#xff0c;如下图所示&#xff1a; 此时可以使⽤以下⽅式解决。 1. 在 Idea 项⽬上右键 2. 选中 Maven 选项 选中 Maven 之后&#…

Vue3状态管理: Pinia使用技巧与最佳实践

Vue3状态管理: Pinia使用技巧与最佳实践 随着Web应用复杂度的提升&#xff0c;前端状态管理变得愈发重要。而在Vue3中&#xff0c;Pinia作为一种全新的状态管理工具&#xff0c;为我们提供了更加灵活和强大的状态管理解决方案。本文将从Pinia的基本概念入手&#xff0c;深入探讨…

从零开始实现一个双向循环链表:C语言实战

文章目录 1链表的再次介绍2为什么选择双向循环链表&#xff1f;3代码实现&#xff1a;从初始化到销毁1. 定义链表节点2. 初始化链表3. 插入和删除节点4. 链表的其他操作5. 打印链表和判断链表是否为空6. 销毁链表 4测试代码5链表种类介绍6链表与顺序表的区别7存储金字塔L0: 寄存…

AI推理性能之王-Groq公司开发的LPU芯片

Groq公司开发的LPU&#xff08;Language Processing Unit&#xff0c;语言处理单元&#xff09;芯片是一种专为加速大规模语言模型&#xff08;LLM&#xff09;和其他自然语言处理任务而设计的新型AI处理器。以下是对其技术特点、性能优势及市场影响的深度介绍&#xff1a; 技…

【玩转 Postman 接口测试与开发2_016】第13章:在 Postman 中实现契约测试(Contract Testing)与 API 接口验证(上)

《API Testing and Development with Postman》最新第二版封面 文章目录 第十三章 契约测试与 API 接口验证1 契约测试的概念2 契约测试的工作原理3 契约测试的分类4 DeepSeek 给出的契约测试相关背景5 契约测试在 Postman 中的创建方法6 API 实例的基本用法7 API 实例的类型实…

The specified Gradle distribution ‘gradle-bin.zip‘ does not exist.

The specified Gradle distribution ‘https://services.gradle.org/distributions/gradle-bin.zip’ does not exist. distributionUrl不存在&#xff0c;关联不上&#xff0c;下载不了&#xff0c;那就匹配一个能下载的 distributionUrlhttps://services.gradle.org/distrib…

【Linux系统】线程:认识线程、线程与进程统一理解

一、更新认知 之前的认知 进程&#xff1a;一个执行起来的程序。进程 内核数据结构 代码和数据线程&#xff1a;执行流&#xff0c;执行粒度比进程要更细。是进程内部的一个执行分值 更新认识&#xff1a; a. 进程是承担分配系统资源的基本实体b. 线程是OS调度的基本单位 …

请求响应(接上篇)

请求 日期参数 需要在前面加上一个注解DateTimeFormat来接收传入的参数的值 Json参数 JSON参数&#xff1a;JSON数据键名与形参对象属性名相同&#xff0c;定义POJO类型形参即可接收参数&#xff0c;需要使用 RequestBody 标识 通过RequestBody将JSON格式的数据封装到实体类…

Linux提权--SUDO提权

​sudo​ 是 Linux 中常用的特权管理工具&#xff0c;允许普通用户以其他用户&#xff08;通常是 root 用户&#xff09;的身份运行命令。如果配置不当&#xff0c;攻击者可能通过滥用 sudo​ 权限来提升自己的权限。 一.常见的 sudo 提权方法&#xff1a; 误配置的 sudo 权限&…

【Elasticsearch】filter聚合

在Elasticsearch中&#xff0c;Filter聚合是一种单桶聚合&#xff0c;用于根据特定的查询条件筛选文档&#xff0c;并对筛选后的文档集合进行进一步的聚合分析。它允许用户在执行聚合操作之前&#xff0c;先过滤出符合某些条件的文档&#xff0c;从而更精确地分析数据。 Filter…

Colorful/七彩虹 隐星P15 TA 24 原厂Win11 家庭版系统 带F9 Colorful一键恢复功能

Colorful/七彩虹 隐星P15 TA 24 原厂Win11 家庭中文版系统 带F9 Colorful一键恢复功能 自动重建COLORFUL RECOVERY功能 带所有随机软件和机型专用驱动 支持机型&#xff1a;隐星P15 TA 24 文件下载&#xff1a;asusoem.cn/745.html 文件格式&#xff1a;ISO 系统版本&…

实时波形与频谱分析———傅立叶变换

实时波形与频谱分析&#xff1a;一个交互式动画演示 在信号处理领域&#xff0c;时域波形和频域频谱是理解信号特性的重要工具。通过时域波形&#xff0c;我们可以直观地观察信号随时间的变化&#xff0c;而频域频谱则揭示了信号中所包含的频率成分及其幅值。为了帮助大家更好…

03链表+栈+队列(D1_链表(D1_基础学习))

目录 一、什么是链表 二、基本操作 三、为什么要使用链表 四、为什么能够在常数时间访问数组元素 数组优点 数组缺点 五、动态数组诞生 链表优点 链表缺点 六、链表、数组和动态数组的对比 七、 链表种类 1. 单向链表 2. 双向链表 3. 循环链表 八、链表衍生 ...…

企业微信开发012_使用WxJava企业微信开发框架_封装第三方应用企业微信开发005_多企业授权实现---企业微信开发014

这里主要说一下如何授权的思路,如何来做,其实非常简单, 如果你有很多企业微信需要授权以后才能使用自己开发的,第三方企业微信功能,那么 首先,在企业列表中,你可以给某个企业去配置,这个企业,他对应的企业微信的,比如, 这个企业的企业id,cropID,当然还可以有,比如企业名称,用…