一、概述

记录时间 [2025-08-29]

前置文章

网络编程 01:计算机网络概述,网络的作用,网络通信的要素,以及网络通信协议与分层模型

网络编程 02:IP 地址,IP 地址的作用、分类,通过 Java 实现 IP 地址的信息获取

网络编程 03:端口的定义、分类,端口映射,通过 Java 实现了 IP 和端口的信息获取

本文讲述网络编程相关知识——TCP连接,包括客户端与服务器的区别,如何实现 TCP 聊天及文件上传等。

同时,文章简单介绍了 Tomcat(服务器)的相关使用。


关于创作纪念日

维持现状。512 纪念日快乐。

里程碑专区



二、TCP

1. TCP 聊天

思路整理

客户端和服务器之间如何进行通信——创建连接 + 收发消息。

客户端

  • 连接服务器 Socket
  • 发送消息

服务器

  • 建立服务的端口 ServerSocket
  • 等待用户的连接 accept
  • 接收用户消息

客户端和服务器之间收发消息通过 I/O 流来实现。

  • 发送消息,socket.getOutputStream()
  • 接收消息,socket.getInputStream()

为防止接收消息乱码,接收方需要使用管道流来处理接收到的消息。

  • new ByteArrayOutputStream()

所有资源在使用后都需要正确关闭,如,socket,serverSocket 等。

  • 关闭资源的顺序为:先开后关
  • 关闭资源前要先判断它是否为空,非空则关闭;
  • 关闭资源操作需要抛出异常。

服务器代码实现

服务器先启动,处在监听过程中,等待客户端的连接。

服务器有一个地址(IP + Port),通过这个地址,客户端才能和服务器连接。

通过 serverSocket.accept() 获取连接过来的客户端,就是客户端的 socket

然后读取客户端的信息。

经过管道处理后,输出信息。

结束后关闭资源。


import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;// 服务端
public class TcpServerDemo01 {public static void main(String[] args) {// 服务端地址ServerSocket serverSocket = null;// 连接过来的客户端Socket socket = null;// 输入流InputStream is = null;// 管道流ByteArrayOutputStream baos = null;try {// 1. 我得有一个地址serverSocket = new ServerSocket(9999);// 循环等待客户端连接过来while (true) {// 2. 等待客户端连接过来socket = serverSocket.accept();// 3. 读取客户端的消息// 消息从客户端流出 Out,流进服务器 Inputis = socket.getInputStream();// 管道流// 给流进来的消息套一个管道,得到从管道中流出来的消息,所有用 Outputbaos = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len;while ((len = is.read(buffer)) != -1) {baos.write(buffer, 0, len);}System.out.println(baos.toString());}} catch (IOException e) {e.printStackTrace();} finally {// 4. 关闭资源, 判非空, 然后先开后关// null 了就没必要关了if (baos != null) {try {baos.close();} catch (IOException e) {e.printStackTrace();}}if (is != null) {try {is.close();} catch (IOException e) {e.printStackTrace();}}if (socket != null) {try {socket.close();} catch (IOException e) {e.printStackTrace();}}if (serverSocket != null) {try {serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}}
}

客户端代码实现

客户端通过服务器的地址(IP + Port)连接上服务器,连接的方式是 socket

客户端给服务器发消息。

结束后关闭资源。


import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;// 客户端
public class TcpClientDemo01 {public static void main(String[] args) {// 客户端连接Socket socket = null;// 输出流OutputStream os =  null;try {// 1. 要知道服务器的地址, 端口号InetAddress serverIP = InetAddress.getByName("127.0.0.1");int port = 9999;// 2. 创建一个 socket 连接socket = new Socket(serverIP, port);// 3. 发送 IO 消息流os = socket.getOutputStream();os.write("你好,欢迎".getBytes());} catch (Exception e) {e.printStackTrace();} finally {// 4. 关闭资源, 判非空, 然后先开后关if (os != null) {try {os.close();} catch (IOException e) {e.printStackTrace();}}if (socket != null) {try {socket.close();} catch (IOException e) {e.printStackTrace();}}}}
}

2. TCP 文件上传

文件流,流的概念

客户端给服务端传文件:

  • 文件通过文件管道流出:客户端中,先流入(In)文件管道,再流出(Out)去到服务端。
  • 文件流入(In)服务端,流入要读(read);服务端用文件管道流出(Out),流出要写(write), 就是保存。

就相当于客户端流出,到服务端流入,然后它们自己可以套管道,管道一头流入,另一头流出。


流入要读(read), 流出要写(write)

while ((len = fis.read(buffer)) != -1) {os.write(buffer, 0, len);
}

工作目录

当我们要读取一个文件时,得先知道该文件的位置,也就是文件路径。

new File("file"):获取项目文件的方法,需要传入的参数是文件路径,如果是相对路径的话,起始路径为当前 Java 项目的工作目录。

在项目中有一个图片资源,如何获取这个图片的相对路径呢?需要通过 Java 项目的工作目录。


获取当前 Java 项目的工作目录的方式:

public class TestPath {public static void main(String[] args) {String currentDir = System.getProperty("user.dir");System.out.println("当前工作目录: " + currentDir);}
}

例如:

当前工作目录为:C:\JavaSE

NetStudyJavaSE 项目中的一个模块,图片资源 tx.jpg 位于 JavaSE/NetStudy 目录下;

那么 tx.jpg 的获取方式是:new File("NetStudy/tx.jpg")


服务器代码实现

服务器监听、等待客户端的连接。

接收客户端发送过来的文件,通过文件管道流处理后,保存文件。(这里的文件是一张图片)

通知客户端,文件接收完成。

结束后关闭资源。


import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;// 服务端
public class TcpServerDemo02 {public static void main(String[] args) throws Exception {// 1. 创建服务, 给出连接的端口ServerSocket serverSocket = new ServerSocket(9000);// 2. 监听客户端的连接// 一直等待, 会阻塞直到有客户端连接// 这个 socket 就是客户端的 socketSocket socket = serverSocket.accept();// 3. 获取输入流// 创建一个输入流,用来输入客户端的流InputStream is = socket.getInputStream();// 4. 文件输出, 接收客户端的文件// 用文件管道流写出文件, 给出文件保存到位置和文件名FileOutputStream fos = new FileOutputStream(new File("NetStudy/receive.jpg"));byte[] buffer = new byte[1024];int len;while ((len = is.read(buffer)) != -1) {fos.write(buffer, 0, len);}// 5. 通知客户端, 文件接收完成// 创建一个输出流, 用来输出给客户端OutputStream os = socket.getOutputStream();// 传信息给客户端os.write("文件已被服务端接收完成".getBytes());// 6. 关闭资源os.close();fos.close();is.close();socket.close();serverSocket.close();}
}

客户端代码实现

文件先通过文件管道流读入项目里,然后才能通过 socket 发送。

建立 socket 连接后,向服务器发送文件。

文件发送完毕后,结束输出流,并告知服务器。(因为服务器和客户端用的是同一个 socket,如果文件发送完不结束流的话,会影响后面的消息发送和接收)

接收服务器发送的 “完成信号”。

结束后关闭资源。


import java.io.*;
import java.net.InetAddress;
import java.net.Socket;// 客户端
public class TcpClientDemo02 {public static void main(String[] args) throws Exception {// 1. 建立服务端连接,ip+portSocket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);// 2. 创建一个输出流// 用来输出给服务端OutputStream os = socket.getOutputStream();// 3. 传文件给服务端// 读取文件: 文件输入流, 先把文件输入管道,管道才能读出来// System.getProperty("user.dir"); 获取项目的工作目录// 获取 tx.jpg 的相对位置FileInputStream fis = new FileInputStream(new File("NetStudy/tx.jpg"));// 读出文件管道流中的文件, 并向服务端写出文件byte[] buffer = new byte[1024];int len;while ((len = fis.read(buffer)) != -1) {os.write(buffer, 0, len);}// 4. 通知服务端文件传输完毕socket.shutdownOutput();System.out.println("通知服务端文件传输完毕");// 5. 确定服务端接收完毕, 才能断开连接// 收到服务端的完成信号后,断开连接// 创建一个输入流,用来接收服务端的流InputStream is = socket.getInputStream();// 用管道流写出文件ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] buffer2 = new byte[1024];int len2;while ((len2 = is.read(buffer2)) != -1) {baos.write(buffer2, 0, len2);}// 输出管道流里的内容System.out.println(baos.toString());// 6. 关闭资源baos.close();is.close();fis.close();os.close();socket.close();}
}


三、使用 Tomcat

在前面的 TCP 中,我们讲到了客户端与服务器(Client/Server),服务器就是用来接收客户端的请求的。

而 Tomcat,就是一个充当服务器的角色。


1. 启动 Tomcat

可以通过脚本启动,双击 bin 目录下的 startup.bat 即可。

默认在 8080 端口下启动,启动成功后可通过 localhost:8080 进行访问。

如果端口被占用,则无法成功启动。

在这里插入图片描述


2. Tomcat 乱码

Tomcat 启动过程中会打印日志信息,不难发现,日志信息中存在乱码现象

导致乱码的原因:字符编码在解码过程中选择了错误的解码方式。

解码规范 / 方式:GBK,UTF-8 等。

文件在计算机中是以字符编码的形式存储的,而我们平常看到文字是字符串形式的。这之间就有编码和解码两个操作。

而 GBK 这类规范就是告诉计算机应该用何种方式进行编码或解码。


那么,如果一个文件是用 GBK 进行编码的,却使用 UTF-8 进行解码,那么就会导致乱码。正所谓 “解铃还须系铃人”,GBK 的编码需要用 GBK 来解码,UTF-8 同理。


conf 目录下,有日志配置文件 logging.properties,在里面可以修改编码 / 解码方式。

  • CMD 选择 GBK
  • IDEA 选择 UTF-8

在这里插入图片描述


在这里插入图片描述


要解决 IDEA 控制台乱码,需要同时设置 JVM 加载 .class 文件时使用 UTF-8 字符集。

-Dfile.encoding=UTF-8

在这里插入图片描述


3. Tomcat 访问部署的资源

启动 Tomcat 后,可以访问其部署的资源,在 webapps 目录下。

访问根目录:localhost:8080

访问自定义资源:webapps 目录下的 test 中的 hello.txt 文件。


http://localhost:8080/test/hello.txt


参考资料

狂神说 - 网络编程:https://www.bilibili.com/video/BV1LJ411z7vY

Java 8 帮助文档:https://docs.oracle.com/javase/8/docs/api/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/94947.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/94947.shtml
英文地址,请注明出处:http://en.pswp.cn/web/94947.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最小生成树——Kruskal

标题什么是生成树? 对于一张无向图,由nnn个顶点和n−1n-1n−1条边构成地联通子图,叫做这个无向图 生成树 最小生成树就是指边权之和最小的生成树 如何求最小生成树? Kruskal 介绍: 存图时只存每条边地起点、终点,…

ADFS 和 OAuth 的区别

ADFS 和 OAuth 的区别 ADFS(Active Directory Federation Services)和 OAuth 都是身份认证与授权领域的技术,但它们的设计目标、应用场景和实现方式有显著区别。以下从核心定义、技术特性、应用场景等方面详细对比: 核心定义与设计目标 技术 核心定义 设计目标 ADFS 微软…

神经网络参数量计算详解

1. 神经网络参数量计算基本原理 1.1 什么是神经网络参数 神经网络的参数主要包括: 权重(Weights):连接不同神经元之间的权重矩阵偏置(Bias):每个神经元的偏置项批归一化参数:BatchNo…

手写链路追踪

1. 什么是链路追踪 链路追踪是指在分布式系统中,将一次请求的处理过程进行记录并聚合展示的一种方法。目的是将一次分布式请求的调用情况集中在一处展示,如各个服务节点上的耗时、请求具体到达哪台机器上、每个服务节点的请求状态等。这样就可以轻松了解…

从零开始的python学习——常量与变量

ʕ • ᴥ • ʔ づ♡ど 🎉 欢迎点赞支持🎉 个人主页:励志不掉头发的内向程序员; 专栏主页:python学习专栏; 文章目录 前言 一、常量和表达式 二、变量类型 2.1、什么是变量 2.2、变量语法 (1&a…

基于51单片机环境监测设计 光照 PM2.5粉尘 温湿度 2.4G无线通信

1 系统功能介绍 本设计是一套 基于51单片机的环境监测系统,能够实时采集环境光照、PM2.5、温湿度等参数,并通过 2.4G无线模块 NRF24L01 实现数据传输。系统具备本地显示与报警功能,可通过按键设置各类阈值和时间,方便用户进行环境…

【Flask】测试平台开发,产品管理实现添加功能-第五篇

概述在前面的几篇开发文章中,我们只是让数据在界面上进行了展示,但是没有添加按钮的功能,接下来我们需要开发一个添加的按钮,用户产品功能的创建和添加抽公共数据链接方法添加接口掌握post实现和请求数据处理前端掌握Button\Dilog…

循环高级(2)

6.练习3 打印九九乘法表7.练习3 制表符详解对齐不了原因:name补到8zhangsan本身就是8,补完就变成16解决办法:1.去掉zhangsan\t,这样前后都是82.name后面加2个\t加一个\t,name\t就是占8个,再加一个\t,就变成…

盒马生鲜 小程序 逆向分析

声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 逆向分析 部分python代码 params {&…

【Linux系统】线程控制

1. POSIX线程库 (pthreads)POSIX线程(通常称为pthreads)是IEEE制定的操作系统线程API标准。Linux系统通过glibc库实现了这个标准,提供了创建和管理线程的一系列函数。核心特性命名约定:绝大多数函数都以 pthread_ 开头&#xff0c…

【Spring Cloud Alibaba】前置知识

【Spring Cloud Alibaba】前置知识1. 微服务介绍1.1 系统架构的演变1.1.1 单体应用架构1.1.2 垂直应用架构1.1.3 分布式架构1.1.3.1 SOA架构1.1.4 微服务架构1. 微服务介绍 1.1 系统架构的演变 随着互联网的发展,网站应用的规模也在不断的扩大,进而导致…

2025互联网大厂Java面试1000道题目及参考答案

Java学到什么程度可以面试工作? 要达到能够面试Java开发工作的水平,需要掌握以下几个方面的知识和技能: 1. 基础扎实:熟悉Java语法、面向对象编程概念、异常处理、I/O流等基础知识。这是所有Java开发者必备的基础,也…

记录:HSD部署(未完成)

建数据库 相关文档:Confluence准备:CA文件和备份用的aws key。 CA文件:在namespace添加trust-injectionenabled的标签,会自动生成。 aws key:生成cnpg-backup-creds的secret。安装: 从git仓库获取values模…

【AI】提示词与自然语言处理:从NLP视角看提示词的作用机制

提示词与自然语言处理:从 NLP 视角看提示词的作用机制在人工智能快速发展的今天,大模型成为了人们关注的焦点。而要让大模型更好地理解人类意图、完成各种任务,提示词扮演着关键角色。从自然语言处理(NLP)的角度来看&a…

2025.8.29机械臂实战项目

好久没给大家更新了,上周末大学大四开学,所以停更了几天,回来后在做项目,接下来的几篇文章,给大家带来几个项目,第一个介绍的是机械臂操作,说是机械臂操作,简单来说,就是…

【机器学习基础】机器学习的要素:任务T、性能度量P和经验E

第一章 机器学习的本质与理论框架 机器学习作为人工智能领域的核心支柱,其理论基础可以追溯到20世纪中叶的统计学习理论。Tom Mitchell在其1997年的经典著作《Machine Learning》中给出了一个至今仍被广泛引用的学习定义:"对于某类任务T和性能度量P,一个计算机程序被认…

wav音频转C语言样点数组

WAV to C Header Converter 将WAV音频文件转换为C语言头文件的Python脚本,支持将音频数据嵌入到C/C项目中。 功能特性 音频格式支持 PCM格式:支持8位、16位、24位、32位PCM音频IEEE Float格式:支持32位浮点音频多声道:支持单声道、…

01.《基础入门:了解网络的基本概念》

网络基础 文章目录网络基础网络通信核心原理网络通信定义信息传递过程关键术语解释网络的分类网络参考模型OSI 参考模型各层核心工作分层核心原则TCP/IP 参考模型(4 层 / 5 层,实际应用模型)TCP/IP 与 OSI 模型的对应关系传输层核心协议&…

基于vue驾校管理系统的设计与实现5hl93(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表:项目功能:学员,教练,教练信息,预约信息,场地信息,时间安排,车辆信息,预约练车,时间段,驾校场地信息,驾校车辆信息,预约报名开题报告内容:一、选题背景与意义背景随着汽车保有量持续增长,驾校行业规模不断扩大&am…

灰度思维:解锁世界原有本色的密码

摘要本文深入探讨灰度思维的概念内涵及其在处理他人评价中的应用价值。研究指出,灰度思维作为一种超越非黑即白的思维方式,能够帮助个体以更客观、全面的态度接受他人评价的片面性,从而促进个人成长和人际关系和谐。文章分析了他人评价片面性…