Java实战报错 tcp

为什么报错tcp

Preview

从图片中的错误信息来看,程序遇到了 java.net.BindException,具体错误信息是 "Address already in use: bind"。这意味着你的程序试图绑定到一个已经被其他进程占用的端口(在本例中是9999端口)。

以下是一些可能的原因和解决方法:

  1. 检查是否有其他进程正在使用该端口

    • 在Windows上,可以使用命令 netstat -ano | findstr :9999 来查找正在使用9999端口的进程。
    • 在Linux或Mac上,可以使用命令 netstat -tuln | grep :9999
  2. 终止占用该端口的进程

    • 如果找到了占用端口的进程,可以通过其PID来终止它。例如,在Windows上使用 taskkill /PID <PID>,在Linux或Mac上使用 kill <PID>
  3. 更改端口号

    • 如果无法终止占用端口的进程,或者希望避免冲突,你可以修改代码中的端口号。例如,将 new ServerSocket(9999); 改为 new ServerSocket(9998); 或其他未被占用的端口。
  4. 确保服务器没有重复启动

    • 确保在同一台机器上没有多次启动同一个服务器实例,因为这也会导致端口冲突。
  5. 检查防火墙设置

    • 有时防火墙可能会阻止某些端口的访问。检查防火墙设置,确保9999端口没有被阻止。
  6. 使用随机端口

    • 如果你不确定哪个端口可用,可以使用 ServerSocket serverSocket = new ServerSocket(0);,这样系统会自动分配一个可用的端口。

接口改成9998后解决!

package demotcp1; import java.io.DataInputStream; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; public class ServerDemo1 { public static void main(String[] args) throws Exception{ //ServerSocket对象 ServerSocket ss = new ServerSocket(9999); //阻塞 等待连接,有人链接就会返回Socket Socket s = ss.accept(); //收取数据:用输入流 InputStream is = s.getInputStream(); //包装 DataInputStream dis =new DataInputStream(is); //按照类型对应读取数据int+String int i1=dis.readInt(); System.out.println("第一个消息:"+i1); String s2 = dis.readUTF(); System.out.println("第二个消息:"+s2); //谁发的? System.out.println("客户端ip"+s.getInetAddress().getHostAddress()); System.out.println("客户端端口"+s.getPort()); while (true) { String swhile = dis.readUTF(); System.out.println("消息:"+swhile); //服务端不用关管道,客户端关了会自动结束 } } } 报错:D:\jv\bin\java.exe "-javaagent:D:\idea\IntelliJ IDEA Community Edition 2024.3.2.2\lib\idea_rt.jar=50709:D:\idea\IntelliJ IDEA Community Edition 2024.3.2.2\bin" -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath D:\codeJava\Javaseai\out\production\20250409;D:\codeJava\Javaseai\lib\junit-4.13.1.jar;D:\codeJava\Javaseai\lib\hamcrest-core-1.3.jar demotcp1.ClientDemo1 Exception in thread "main" java.net.ConnectException: Connection refused: connect at java.base/sun.nio.ch.Net.connect0(Native Method) at java.base/sun.nio.ch.Net.connect(Net.java:589) at java.base/sun.nio.ch.Net.connect(Net.java:578) at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:583) at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327) at java.base/java.net.Socket.connect(Socket.java:751) at java.base/java.net.Socket.connect(Socket.java:686) at java.base/java.net.Socket.<init>(Socket.java:555) at java.base/java.net.Socket.<init>(Socket.java:324) at demotcp1.ClientDemo1.main(ClientDemo1.java:14) 进程已结束,退出代码为 1

根据你提供的代码和错误信息,问题出在客户端(ClientDemo1)尝试连接服务器时,未能成功建立连接。以下是可能的原因及解决方法:


错误分析:

  1. java.net.ConnectException: Connection refused: connect

    • 这个错误表示客户端尝试连接服务器时,服务器未监听指定的端口,或者服务器未运行。
    • 通常是因为以下原因之一:
      • 服务器程序未启动或未正确绑定到指定端口。
      • 客户端连接的 IP 地址或端口号与服务器监听的地址或端口不匹配。
      • 防火墙或其他网络配置阻止了客户端与服务器之间的通信。
  2. 关键点:

    • 你的服务器代码绑定了 9999 端口(new ServerSocket(9999)),因此客户端必须连接到同一端口。
    • 如果服务器未运行,客户端尝试连接时会失败。

解决方法:
1. 检查服务器是否正在运行
  • 确保服务器程序(ServerDemo1)已启动并正在监听 9999 端口。
  • 在终端运行服务器程序后,应该能看到类似以下输出:
     

    深色版本

    Server is listening on port 9999...
  • 如果没有看到类似的输出,说明服务器未正确启动。
2. 检查客户端代码
  • 客户端代码中,确保连接的是正确的 IP 地址和端口号。例如:
     java 

    深色版本

    Socket socket = new Socket("127.0.0.1", 9999);
  • 如果服务器运行在同一台机器上,使用 127.0.0.1 或 localhost 即可。
  • 如果服务器运行在其他机器上,确保使用服务器的实际 IP 地址。
3. 确保端口未被占用
  • 使用以下命令检查 9999 端口是否被占用:
    • Windows:
       cmd 

      深色版本

      netstat -ano | findstr :9999
    • Linux/Mac:
       bash 

      深色版本

      lsof -i :9999
  • 如果端口已被占用,可以选择更换端口号,或者终止占用该端口的进程。
4. 检查防火墙设置
  • 如果服务器和客户端运行在不同的机器上,确保防火墙允许 9999 端口的通信。
  • 可以临时关闭防火墙进行测试,或者添加规则允许该端口。
5. 示例客户端代码
  • 确保客户端代码如下所示,并且与服务器代码匹配:
     java 

    深色版本

    package demotcp1;
    
    import java.io.DataOutputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    
    public class ClientDemo1 {
        public static void main(String[] args) throws Exception {
            // 创建Socket对象,连接到服务器
            Socket socket = new Socket("127.0.0.1", 9999);
    
            // 发送数据:用输出流
            OutputStream os = socket.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);
    
            // 按照类型发送数据
            dos.writeInt(123);
            dos.writeUTF("Hello from client");
    
            // 关闭资源
            dos.close();
            os.close();
            socket.close();
        }
    }

调试步骤:

  1. 启动服务器程序(ServerDemo1)。
  2. 启动客户端程序(ClientDemo1)。
  3. 观察服务器端是否有输出,例如:
     

    深色版本

    第一个消息:123
    第二个消息:Hello from client
    客户端ip:127.0.0.1
    客户端端口:XXXXX
  4. 如果仍然报错,检查以下内容:
    • 服务器是否正常运行。
    • 客户端连接的 IP 和端口是否正确。
    • 是否有防火墙或其他网络限制。

总结:

  • 确保服务器程序先运行并监听 9999 端口。
  • 确保客户端连接到正确的 IP 和端口。
  • 检查端口占用和防火墙设置。
  • 如果问题仍未解决,请提供更多上下文信息(如客户端代码、完整的错误日志等),以便进一步分析。

代码模式

没有回应

Preview

从你提供的命令行截图来看,你尝试使用 netstat -ano | findstr :9999 来检查端口 9999 是否被占用,但没有得到任何回应。这通常意味着端口 9999 当前没有被任何进程占用。

可能的原因和解决方法:

  1. 服务器未启动

    • 确保你的服务器程序(ServerDemo1)已经正确启动,并且正在监听端口 9999。
    • 在终端或命令行中运行服务器程序,并确认它是否在监听端口 9999。
  2. 防火墙设置

    • 检查防火墙设置,确保端口 9999 被允许通过。
    • 你可以临时关闭防火墙进行测试,或者添加规则允许该端口。
  3. 网络配置

    • 确保客户端和服务器之间的网络连接正常。
    • 如果服务器和客户端不在同一台机器上,确保它们之间可以互相访问。
  4. 端口被其他进程占用

    • 尝试使用不同的端口号,例如 9090 或其他未被占用的端口。
    • 使用 netstat -ano 命令查看所有开放的端口,确保没有其他进程占用目标端口。

示例步骤:

启动服务器
 

java

深色版本

package demotcp1;

import java.io.DataInputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerDemo1 {
    public static void main(String[] args) throws Exception {
        // 创建 ServerSocket 对象并绑定到 9999 端口
        ServerSocket ss = new ServerSocket(9999);
        System.out.println("Server is listening on port 9999...");

        while (true) {
            // 阻塞等待连接
            Socket s = ss.accept();
            System.out.println("Client connected from " + s.getInetAddress().getHostAddress());

            // 收取数据:用输入流
            InputStream is = s.getInputStream();
            DataInputStream dis = new DataInputStream(is);

            // 按照类型对应读取数据 int + String
            int i1 = dis.readInt();
            System.out.println("第一个消息:" + i1);
            String s2 = dis.readUTF();
            System.out.println("第二个消息:" + s2);

            // 循环读取消息
            while (true) {
                String swhile = dis.readUTF();
                System.out.println("消息:" + swhile);
            }
        }
    }
}
启动客户端
 

java

深色版本

package demotcp1;

import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;

public class ClientDemo1 {
    public static void main(String[] args) throws Exception {
        // 创建 Socket 对象,连接到服务器
        Socket socket = new Socket("127.0.0.1", 9999);

        // 发送数据:用输出流
        OutputStream os = socket.getOutputStream();
        DataOutputStream dos = new DataOutputStream(os);

        // 按照类型发送数据
        dos.writeInt(123);
        dos.writeUTF("Hello from client");

        // 关闭资源
        dos.close();
        os.close();
        socket.close();
    }
}

测试步骤:

  1. 运行服务器程序,确保它在监听端口 9999。
  2. 运行客户端程序,尝试连接服务器。
  3. 观察服务器端是否有输出,如:
     

    深色版本

    Client connected from 127.0.0.1
    第一个消息:123
    第二个消息:Hello from client

如果仍然遇到问题,请提供更多的错误信息或日志,以便进一步诊断。

我还没运行客户端呢,我先运行的服务端。为什么报错

如果仅运行了服务端程序(ServerDemo1),但仍然报错,那么问题可能出在以下几个方面:


1. 检查服务端代码是否正确运行

  • 确保服务端代码没有任何语法错误或逻辑问题。
  • 运行服务端时,应该能看到类似以下输出:
     

    深色版本

    Server is listening on port 9999...
  • 如果没有看到这样的输出,说明服务端程序未能成功启动。
解决方法:
  • 确保你的服务端代码中 ServerSocket ss = new ServerSocket(9999); 正常执行。
  • 在服务端代码的开头添加调试信息,例如:
     java 

    深色版本

    System.out.println("Starting server...");
    确保程序能够运行到这一行。

2. 端口绑定失败

  • 如果服务端尝试绑定到 9999 端口时失败,可能会抛出异常。例如:
     

    深色版本

    java.net.BindException: Address already in use: bind
  • 这通常是因为端口被其他进程占用。
解决方法:
  • 检查是否有其他进程占用了 9999 端口:
    • Windows:
       cmd 

      深色版本

      netstat -ano | findstr :9999
    • Linux/Mac:
       bash 

      深色版本

      lsof -i :9999
  • 如果端口被占用,可以选择更换端口号,例如改为 9090
     java 

    深色版本

    ServerSocket ss = new ServerSocket(9090);

3. 防火墙或其他网络限制

  • 防火墙可能会阻止程序绑定到指定端口。
解决方法:
  • 暂时关闭防火墙进行测试。
  • 或者在防火墙规则中允许 Java 使用该端口。

4. 权限不足

  • 如果你尝试绑定到低于 1024 的端口(如 80、443),需要管理员权限。
  • 虽然你在使用 9999 端口(高于 1024),但仍需确保运行 Java 的用户有足够的权限。
解决方法:
  • 确保以普通用户权限运行程序即可。
  • 如果仍有问题,尝试以管理员身份运行 IDE 或命令行。

5. Java 环境问题

  • 如果 Java 环境配置不正确,可能导致程序无法正常运行。
解决方法:
  • 确保你的 JDK 版本与代码兼容。
  • 检查 JAVA_HOME 和 PATH 环境变量是否正确配置。
  • 使用以下命令验证 Java 版本:
     bash 

    深色版本

    java -version

6. IDE 配置问题

  • 如果你在 IntelliJ IDEA 或其他 IDE 中运行程序,可能是运行配置有问题。
解决方法:
  • 检查运行配置,确保主类为 demotcp1.ServerDemo1
  • 清理并重新构建项目:
    • 在 IntelliJ IDEA 中:Build > Rebuild Project
  • 确保所有依赖库已正确加载。

7. 完整的服务端代码调试

以下是经过调试的服务端代码,添加了一些额外的日志信息,方便排查问题:

结果是运行的时候运行到别的文件了

java

深色版本

package demotcp1;

import java.io.DataInputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerDemo1 {
    public static void main(String[] args) {
        try {
            System.out.println("Starting server...");
            // 创建 ServerSocket 对象并绑定到 9999 端口
            ServerSocket ss = new ServerSocket(9999);
            System.out.println("Server is listening on port 9999...");

            while (true) {
                // 阻塞等待连接
                Socket s = ss.accept();
                System.out.println("Client connected from " + s.getInetAddress().getHostAddress());

                // 收取数据:用输入流
                InputStream is = s.getInputStream();
                DataInputStream dis = new DataInputStream(is);

                // 按照类型对应读取数据 int + String
                int i1 = dis.readInt();
                System.out.println("第一个消息:" + i1);
                String s2 = dis.readUTF();
                System.out.println("第二个消息:" + s2);

                // 循环读取消息
                while (true) {
                    String swhile = dis.readUTF();
                    System.out.println("消息:" + swhile);
                }
            }
        } catch (Exception e) {
            System.err.println("Error occurred: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

测试步骤:

  1. 运行服务端程序,观察控制台输出。
    • 如果没有输出 Server is listening on port 9999...,说明服务端未成功启动。
    • 如果有异常信息,请提供完整的错误日志。
  2. 如果服务端成功启动,再运行客户端程序进行测试。

总结:

  • 确保服务端代码无误,并能成功绑定到端口。
  • 检查端口是否被占用,或者尝试更换端口号。
  • 确保防火墙和权限设置不会阻止程序运行。
  • 如果仍有问题,请提供完整的错误日志或更多上下文信息,以便进一步分析。

代码模式

为什么会报异常呢

Preview

从你提供的代码片段来看,ServerReader 类继承了 Thread 类,并且有一个构造函数接收一个 Socket 对象作为参数。但是,IDE 提示了一个错误,显示在构造函数的定义上。

错误原因分析

  1. 构造函数未被调用:IDE 提示可能是因为构造函数没有被正确地调用。
  2. 缺少默认构造函数:如果你尝试创建一个 ServerReader 对象而没有传递 Socket 参数,那么需要有一个默认的构造函数。

解决方法

  1. 确保构造函数被正确调用

    • 确保在创建 ServerReader 对象时传递了 Socket 参数。
    • 如果你不希望传递参数,可以添加一个默认构造函数。
  2. 添加默认构造函数

    • 如果你需要一个不带参数的构造函数,可以在类中添加它。

示例代码修改

1. 确保构造函数被正确调用
 

java

深色版本

public class ServerReader extends Thread {
    private Socket s;

    public ServerReader(Socket s) {
        this.s = s;
    }

    public void run() {
        // 收取数据:用输入流
        InputStream is = s.getInputStream();
        DataInputStream dis = new DataInputStream(is);
        // 按照类型对应读取数据 int + String
        int i1 = dis.readInt();
        System.out.println("第一个消息:" + i1);
        String s2 = dis.readUTF();
        System.out.println("第二个消息:" + s2);

        while (true) {
            String swhile = dis.readUTF();
            System.out.println("消息:" + swhile);
        }
    }
}
2. 添加默认构造函数
 

java

深色版本

public class ServerReader extends Thread {
    private Socket s;

    public ServerReader(Socket s) {
        this.s = s;
    }

    // 默认构造函数
    public ServerReader() {
        // 可以在这里进行初始化操作
    }

    public void run() {
        // 收取数据:用输入流
        InputStream is = s.getInputStream();
        DataInputStream dis = new DataInputStream(is);
        // 按照类型对应读取数据 int + String
        int i1 = dis.readInt();
        System.out.println("第一个消息:" + i1);
        String s2 = dis.readUTF();
        System.out.println("第二个消息:" + s2);

        while (true) {
            String swhile = dis.readUTF();
            System.out.println("消息:" + swhile);
        }
    }
}

使用示例

假设你在服务端主程序中使用 ServerReader 类:

 

java

深色版本

public class ServerDemo1 {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(9999);
        System.out.println("Server is listening on port 9999...");

        while (true) {
            Socket s = ss.accept();
            System.out.println("Client connected from " + s.getInetAddress().getHostAddress());

            ServerReader reader = new ServerReader(s);
            reader.start();
        }
    }
}

总结

  • 确保 ServerReader 的构造函数被正确调用,并且传递了 Socket 参数。
  • 如果需要,默认构造函数也可以添加,但通常情况下,传递 Socket 参数是必要的。

通过这些修改,你应该能够解决 IDE 提示的错误,并确保 ServerReader 类能够正常工作。

这个override有什么问题吗?

Preview

从你提供的代码片段来看,@Override 注解用于覆盖 Thread 类中的 run 方法。IDE 提示的错误可能是因为以下几个原因:

  1. 构造函数未被调用:确保在创建 ServerReader 对象时传递了 Socket 参数。
  2. 变量未初始化:确保 s 变量已经被正确初始化。

代码分析

 

java

深色版本

public class ServerReader extends Thread {
    private Socket s;

    public ServerReader(Socket s) {
        this.s = s;
    }

    @Override
    public void run() {
        // 收取数据:用输入流
        InputStream is = s.getInputStream();
        DataInputStream dis = new DataInputStream(is);
        
        // 按照类型对应读取数据 int + String
        int i1 = dis.readInt();
        System.out.println("第一个消息:" + i1);
        String s2 = dis.readUTF();
        System.out.println("第二个消息:" + s2);

        while (true) {
            String swhile = dis.readUTF();
            System.out.println("消息:" + swhile);
        }
    }
}

错误提示解释

  • IDE 提示 0 个用法:这通常意味着 run 方法没有被正确地调用或使用。
  • @Override 标注:这个标注表示 run 方法是覆盖父类(Thread)的方法。如果 run 方法没有被正确地调用,那么 @Override 标注可能会失效。

解决方法

  1. 确保构造函数被正确调用

    • 确保在创建 ServerReader 对象时传递了 Socket 参数。
    • 示例代码如下:
     java 

    深色版本

    public class ServerDemo1 {
        public static void main(String[] args) throws Exception {
            ServerSocket ss = new ServerSocket(9999);
            System.out.println("Server is listening on port 9999...");
    
            while (true) {
                Socket s = ss.accept();
                System.out.println("Client connected from " + s.getInetAddress().getHostAddress());
    
                ServerReader reader = new ServerReader(s);
                reader.start(); // 启动线程
            }
        }
    }
  2. 检查 Socket 是否正确初始化

    • 确保 Socket 对象在 ServerReader 构造函数中被正确初始化。
  3. 确保 run 方法被调用

    • 在创建 ServerReader 对象后,必须调用 start() 方法来启动线程。

完整示例

 

java

深色版本

public class ServerReader extends Thread {
    private Socket s;

    public ServerReader(Socket s) {
        this.s = s;
    }

    @Override
    public void run() {
        try {
            // 收取数据:用输入流
            InputStream is = s.getInputStream();
            DataInputStream dis = new DataInputStream(is);

            // 按照类型对应读取数据 int + String
            int i1 = dis.readInt();
            System.out.println("第一个消息:" + i1);
            String s2 = dis.readUTF();
            System.out.println("第二个消息:" + s2);

            while (true) {
                String swhile = dis.readUTF();
                System.out.println("消息:" + swhile);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public class ServerDemo1 {
    public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(9999);
        System.out.println("Server is listening on port 9999...");

        while (true) {
            Socket s = ss.accept();
            System.out.println("Client connected from " + s.getInetAddress().getHostAddress());

            ServerReader reader = new ServerReader(s);
            reader.start(); // 启动线程
        }
    }
}

通过这些修改,你应该能够解决 IDE 提示的错误,并确保 ServerReader 类能够正常工作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值