0

0

Java Socket 计算器中减法与乘法失效的根本原因及修复方案

心靈之曲

心靈之曲

发布时间:2026-03-07 10:35:00

|

538人浏览过

|

来源于php中文网

原创

Java Socket 计算器中减法与乘法失效的根本原因及修复方案

本文详解 Java Socket 编程中因误用 InputStream.read() 读取整数导致的运算逻辑错误,并提供基于 DataInputStream/DataOutputStream 的健壮解决方案,确保加、减、乘三类运算在客户端-服务器间准确传输与计算。

本文详解 java socket 编程中因误用 `inputstream.read()` 读取整数导致的运算逻辑错误,并提供基于 `datainputstream`/`dataoutputstream` 的健壮解决方案,确保加、减、乘三类运算在客户端-服务器间准确传输与计算。

在 Java 网络编程中,使用原始 InputStream 和 OutputStream 直接调用 read() / write(int) 方法处理数值,是初学者常见的陷阱——表面看似简洁,实则隐含严重语义缺陷。您遇到的“加法能出结果但减法、乘法结果完全错误”(如输入 5、10、20 时,乘法得 232、减法得 231),根本原因并非逻辑错误,而是数据类型与协议不匹配:InputStream.read() 每次仅读取 1 个字节(byte),并将其无符号扩展为 int(范围 0–255),无法正确表示负数或大于 255 的整数;同理,OutputStream.write(int) 仅写入该 int 的最低 8 位字节

例如,客户端执行:

output.write(5);   // 写入字节 0x05
output.write(10);  // 写入字节 0x0A
output.write(20);  // 写入字节 0x14

服务端 input.read() 依次得到 5、10、20 —— 这看似正常。但当输入 -5 时(如减法测试),output.write(-5) 实际写入的是 (-5) & 0xFF = 251(即字节 0xFB),服务端读到 251,误作正数参与运算,导致结果彻底失真。

此外,原始代码存在另一关键缺陷:未对多字节整数进行序列化约定。Java int 占 4 字节,而 read() 一次只读 1 字节,无法保证跨平台字节序(Big-Endian)一致性,也无法区分数字边界(如 123 和 456 连续写入会变成 123456 的字节流)。

立即学习Java免费学习笔记(深入)”;

✅ 正确解法:使用 DataInputStream 与 DataOutputStream

Post AI
Post AI

博客文章AI生成器

下载

这两者专为网络传输 Java 基本类型设计,严格遵循标准二进制格式(如 int 固定 4 字节、大端序),并提供类型安全的 readInt()/writeInt() 方法,彻底规避字节截断与符号丢失问题。

以下是修复后的完整服务端代码(关键改动已高亮):

import java.io.*;
import java.net.*;

public class CalculatorServer {
    private final ServerSocket server;

    public CalculatorServer() throws IOException {
        this.server = new ServerSocket(8080);
        System.out.println("CalculatorServer started on port 8080");
    }

    public void run() throws IOException {
        while (true) {
            try (Socket client = server.accept();
                 DataInputStream input = new DataInputStream(
                     new BufferedInputStream(client.getInputStream()));
                 DataOutputStream output = new DataOutputStream(
                     new BufferedOutputStream(client.getOutputStream()))) {

                int op = input.readInt();      // ✅ 安全读取 4 字节 int
                int num1 = input.readInt();
                int num2 = input.readInt();
                int num3 = input.readInt();

                int result;
                switch (op) {
                    case 0: result = num1 + num2 + num3; break;
                    case 1: result = num1 - num2 - num3; break; // 5-10-20 = -25
                    case 2: result = num1 * num2 * num3; break; // 5*10*20 = 1000
                    default: result = 0;
                }

                output.writeInt(result); // ✅ 安全写入 4 字节 int
                output.flush();
            }
        }
    }

    public static void main(String[] args) {
        try {
            new CalculatorServer().run();
        } catch (IOException e) {
            System.err.println("Server error: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

对应客户端代码:

import java.io.*;
import java.net.*;

public class CalculatorClient {
    public CalculatorClient() throws IOException {
        try (Socket socket = new Socket("localhost", 8080);
             DataInputStream input = new DataInputStream(
                 new BufferedInputStream(socket.getInputStream()));
             DataOutputStream output = new DataOutputStream(
                 new BufferedOutputStream(socket.getOutputStream()))) {

            // 发送操作码:0=加, 1=减, 2=乘
            output.writeInt(1); // ✅ 减法
            output.writeInt(5);
            output.writeInt(10);
            output.writeInt(20);
            output.flush();

            int response = input.readInt(); // ✅ 正确读取结果
            System.out.println("Result: " + response); // 输出: Result: -25
        }
    }

    public static void main(String[] args) {
        try {
            new CalculatorClient();
        } catch (IOException e) {
            System.err.println("Client error: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

? 关键注意事项:

  • 务必使用 try-with-resources 或显式 close():DataInputStream/DataOutputStream 包装了底层流,关闭外层流会自动关闭内层流,避免资源泄漏。
  • flush() 不可省略:BufferedOutputStream 会缓存数据,flush() 强制将缓冲区内容发送至网络。
  • 操作码与参数需严格对齐:客户端发送顺序必须与服务端读取顺序完全一致(先 op,再 num1/num2/num3)。
  • 异常处理需细化:生产环境应捕获 IOException 子类(如 SocketTimeoutException)并做重试或降级处理。
  • 端口选择:避免使用 1–1023 的特权端口(如原文的 10),推荐 8080、9000 等非特权端口。

通过采用 DataInputStream/DataOutputStream,您不仅解决了当前的减法、乘法失效问题,更构建了可扩展、可维护、符合 Java I/O 规范的网络通信基础。后续如需支持浮点数、字符串或自定义对象,只需替换为 readFloat()、readUTF() 或结合 ObjectInputStream 即可,架构平滑演进。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

333

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

223

2025.10.31

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

138

2026.02.12

数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

333

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

223

2025.10.31

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

138

2026.02.12

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

718

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

219

2023.09.04

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

1

2026.03.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.2万人学习

C# 教程
C# 教程

共94课时 | 10.8万人学习

Java 教程
Java 教程

共578课时 | 77.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号