news 2026/1/31 4:08:24

[服务器应用开发教程]第二节-使用java让服务器忙起来

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[服务器应用开发教程]第二节-使用java让服务器忙起来

第一部分:为什么是java?如何在liunx上安装java?

最核心的一点:java“一次编写,到处运行” 的理念给予了它极为优异的跨平台性能。Java 支持 Linux、Windows、ARM/x86 等环境,并与 Kubernetes、Docker 无缝集成。

只要你的电脑上安装了java jdk环境,无论是Windows还是liunx都可以运行java应用,所以我们的第一步,就是为服务器配置java环境:

方法一:使用宝塔面板安装java jdk:

在软件商店中搜索“java环境管理器”,然后下载安装,完成后打开它:

再选择相应版本安装即可。

方法二:在终端进行操作:

这里以Ubuntu系统安装java17为例:

sudo apt update sudo apt install openjdk-17-jdk -y

无论哪种方法,在安装完成后都可以查询java版本验证:

java -version

如果安装成功,终端会输出如下信息:

第二部分:基于WebSocket的服务器通信原理及简单的信息处理尝试

我们现在知道服务器的ip了,那我们该如何让我们的本地计算机链接到它呢?

答案是使用WebSocket。WebSocket是一种重要的网络通信协议,属于传输层之上的应用层协议,提供全双工通信通道,允许客户端与服务器双向传输数据,提供了一套api接口来使计算机之间能够建立链接。几乎所有的编程语言都支持WebSocket。我们熟知的spring框架中的spring WebSocket就是对前者的封装。

在实际应用中,我们需要根据实际情况来选择使用WebSocket还是spring WebSocket:

WebSocket虽然在编程调用上比较麻烦,但功能可扩展性高。原生 WebSocket 支持通过 RFC 6455 定义的扩展机制(如permessage-deflate压缩、心跳检测)动态增强协议功能,适用于需要深度定制的场景(如高吞吐量二进制数据传输)。

Spring WebSocket在编程使用的简便性上更优,相应的它的扩展灵活性相对弱于前者。Spring WebSocket 通过@MessageMapping@SubscribeMapping等注解,将消息路由和处理逻辑封装为类似 Spring MVC 的声明式编程模型,开发者无需手动处理连接生命周期(如onopenonmessage事件)或底层帧解析。

具体到通信协议中的TCP协议、UDP协议等等我们后面再详细去讲,简单来说,这些协议规定了客户端与服务器之间谁怎样发送数据,谁又如何接收数据等等。

接下来我们讲解基于WebSocket的服务器通信实现功能的关键字段(为方便读代码,这些代码简化去除了异常处理类),假定我们要实现的功能是客户端发送两个数字A和B,服务器返回C=A+B,代码分为服务器端(cloud)与客户端(local)(完整代码在放在最后):

第一步,在本地构造一个包含了服务器ip与端口的local:

//local.java public local(String serverIp, int serverPort) { this.serverIp = serverIp; //服务器ip this.serverPort = serverPort; //服务器端口 }

第二步,创建socket在客户端的服务进程:

//local.java public int sendAndProcessData(int a, int b) throws IOException { Socket socket = new Socket(serverIp, serverPort); // 创建(实例化)客户端套接字,连接到指定IP地址和端口的服务器 PrintWriter out = new PrintWriter(socket.getOutputStream(), true); // 获取套接字的输出流,用于向服务器发送数据 BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); // 获取套接字的输入流,用于读取服务器返回的数据

第三步,创建socket在服务器的进程:

//cloud.java public void start() throws IOException { serverSocket = new ServerSocket(port); //创建(实例化)一个服务器套接字,监听指定端口 System.out.println("服务器启动,监听端口: " + port); while (true) { Socket clientSocket = serverSocket.accept(); // 等待客户端连接请求,当有客户端连接时返回客户端套接字 System.out.println("客户端已连接: " + clientSocket.getInetAddress()); //在建立连接后,输出日志+客户端ip new ClientHandler(clientSocket).start(); // 创建新线程处理客户端请求 } }

第四步,编写服务器与客户端的数据处理逻辑:

//cloud.java private static class ClientHandler extends Thread { private Socket clientSocket; public ClientHandler(Socket socket) { this.clientSocket = socket; } @Override public void run() { try ( BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true) ) { // 读取两个整数 String line = in.readLine(); String[] numbers = line.split(","); int a = Integer.parseInt(numbers[0].trim()); int b = Integer.parseInt(numbers[1].trim()); int c = a + b; // 返回计算结果 out.println(c); System.out.println("处理完成: " + a + " + " + b + " = " + c); clientSocket.close(); } catch (Exception e) { // 简化异常处理 } } }
//local.java的sendAndProcessData的后半部分: // 发送数据A和B String requestData = a + "," + b; out.println(requestData); // 接收处理结果C String response = in.readLine(); int result = Integer.parseInt(response); // 关闭资源 in.close(); out.close(); socket.close(); return result; }

最后一步:编写服务器与客户端的主方法:

//local.java public static void main(String[] args) throws IOException { String serverIp = "xxx.xxx.xxx.xxx"; //替换为你的服务器的ip int serverPort = 1234; //注意别忘了放通服务器防火墙 local client = new local(serverIp, serverPort); int a = 10; int b = 20; int c = client.sendAndProcessData(a, b); System.out.println("发送数据: A=" + a + ", B=" + b); System.out.println("接收结果: C=" + c); }
//cloud.java public static void main(String[] args) throws IOException { cloud server = new cloud(1234); // 一定一定要使用与客户端相同的端口号 server.start(); }

我们来试运行一下代码,先将cloud.java上传到你的服务器当中,再在服务器终端上使用java指令运行cloud.java,再在本地运行local.java:

本地终端输出:

服务器终端输出(涂红部分是客户端ip):

可以体会到,原生WebSocket确实在调用上比较麻烦,在下一节中,我们将研究如何使用spring来连接服务器。

附:本节原生WebSocket实现功能的代码:

客户端(local.java):

// local.java package cloudtest; import java.io.*; import java.net.*; public class local { private String serverIp; private int serverPort; public local(String serverIp, int serverPort) { this.serverIp = serverIp; this.serverPort = serverPort; } public int sendAndProcessData(int a, int b) throws IOException { Socket socket = new Socket(serverIp, serverPort); // 创建客户端套接字,连接到指定IP地址和端口的服务器 PrintWriter out = new PrintWriter(socket.getOutputStream(), true); // 获取套接字的输出流,用于向服务器发送数据 BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); // 获取套接字的输入流,用于读取服务器返回的数据 // 发送数据A和B String requestData = a + "," + b; out.println(requestData); // 接收处理结果C String response = in.readLine(); int result = Integer.parseInt(response); // 关闭资源 in.close(); out.close(); socket.close(); return result; } public static void main(String[] args) throws IOException { String serverIp = "xxx.xxx.xxx.xxx"; int serverPort = 1234; local client = new local(serverIp, serverPort); int a = 10; int b = 20; int c = client.sendAndProcessData(a, b); System.out.println("发送数据: A=" + a + ", B=" + b); System.out.println("接收结果: C=" + c); } }

服务器(cloud.java):

// cloud.java package cloudtest; import java.io.*; import java.net.*; public class cloud { private ServerSocket serverSocket; private int port; public cloud(int port) { this.port = port; } public void start() throws IOException { serverSocket = new ServerSocket(port); //创建(实例化)一个服务器套接字,监听指定端口 System.out.println("服务器启动,监听端口: " + port); while (true) { Socket clientSocket = serverSocket.accept(); // 等待客户端连接请求,当有客户端连接时返回客户端套接字 System.out.println("客户端已连接: " + clientSocket.getInetAddress()); new ClientHandler(clientSocket).start(); // 创建新线程处理客户端请求 } } // 客户端处理线程 private static class ClientHandler extends Thread { private Socket clientSocket; public ClientHandler(Socket socket) { this.clientSocket = socket; } @Override public void run() { try ( BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true) ) { // 读取两个整数 String line = in.readLine(); String[] numbers = line.split(","); int a = Integer.parseInt(numbers[0].trim()); int b = Integer.parseInt(numbers[1].trim()); int c = a + b; // 返回计算结果 out.println(c); System.out.println("处理完成: " + a + " + " + b + " = " + c); clientSocket.close(); } catch (Exception e) { // 简化异常处理 } } } public static void main(String[] args) throws IOException { cloud server = new cloud(1234); // 使用与客户端相同的端口 server.start(); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/30 7:51:52

2025网络安全学习路线 非常详细 推荐学习

关键词:网络安全入门、渗透测试学习、零基础学安全、网络安全学习路线 首先咱们聊聊,学习网络安全方向通常会有哪些问题 1、打基础时间太长 学基础花费很长时间,光语言都有几门,有些人会倒在学习 linux 系统及命令的路上&#…

作者头像 李华
网站建设 2026/1/31 2:49:38

测试必知:线上出现BUG,该怎么办!

在讲解故障处理思路前,先讲一个故障场景(以呼叫中心系统作为一例子): 业务人员反映呼叫中心系统运行缓慢,部份电话在自助语言环节系统处理超时,话务转人工座席,人工座席出现爆线情况。 运维人…

作者头像 李华
网站建设 2026/1/25 5:56:09

【C++】学生管理系统设计与实现丨SQLite数据库版本

摘要 本文详细介绍了一个使用C和SQLite数据库开发的学生管理系统的设计与实现。该系统采用模块化设计,结合了面向对象编程思想和数据库技术,实现了学生信息的增删改查、成绩统计分析、数据持久化等功能。系统具有结构清晰、功能完整、数据安全等特点&am…

作者头像 李华
网站建设 2026/1/26 3:12:35

第55集科立分板机:PCB激光分板机的效率如何

PCB激光分板机的效率较高,其高效性主要体现在以下几个方面: 切割速度快: 激光光束的移动速度极快,能够实现高速切割,显著提高分板效率,尤其在大批量生产中优势更为明显。例如,部分设备在切割0…

作者头像 李华
网站建设 2026/1/22 4:12:34

28、UNIX 终端操作与测试实用指南

UNIX 终端操作与测试实用指南 1. stty 命令的使用 stty 命令可用于设置当前提供标准输入的终端设备的 I/O 选项。单独执行 stty -a 命令,能显示所有可用选项的当前设置: rocket 8% stty -a speed 9600 baud; line = 1; 0 rows; 0 columns intr = ^C; quit = ^\; erase …

作者头像 李华
网站建设 2026/1/30 7:16:19

31、UNIX实用技巧:ASCII表与经典编辑器使用指南

UNIX实用技巧:ASCII表与经典编辑器使用指南 1. UNIX中的ASCII表 在UNIX系统里,ASCII表虽然不常用,但在某些特定时刻,它的重要性就凸显出来了。然而,要找到这个表却并非易事。不过现在不用担心,其实它就存在于系统的手册页中,适用于AT&T和部分BSD系统。 要查看ASC…

作者头像 李华