首页 > 解决方案 > 当涉及到 java 套接字时,我不明白 try catch 的范围

问题描述

我在 13 年级,并决定在我的计算机科学课程中使用 java 制作一个小型聊天程序。我不得不从头开始学习网络方面的知识,而我的老师对此并不熟悉,因此他们很难回答我的问题。我有一个客户端程序和一个服务器程序,它们通过我创建的套接字进行通信,我的问题是我不明白 try 捕获对我的代码的影响。我对网络非常着迷,这就是为什么我选择它的原因很清楚这将是一个挑战,我会在下面留下我的代码和我遇到的错误。如果你能给我任何关于如何解决我的问题并让我的代码“更好”的提示,那将是非常棒的。另外请考虑到我只知道java大约一年了,而且我还是个新手,而且这是我关于堆栈溢出的第一个问题!

客户代码:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package oclient;

import  java.net.*;
import  java.io.*;
import com.dosse.upnp.UPnP;
import java.util.Scanner;
/**
 *
 * @author sgmud
 */
public class CClient {
    public Socket CSocket;
    public PrintWriter out;
    public BufferedReader in;
    
    
    public int GetPort(){
        Scanner scan = new Scanner(System.in);
        System.out.println("please enter the port number");
        int PortNum = scan.nextInt();
        return PortNum;
    }
    
    public String GetAddress(){
        Scanner scan = new Scanner(System.in);
        System.out.println("Please enter the IP address of the host");
        String Address = scan.nextLine();
        return Address;
    }
    
    public void StartConnection(String ip, int port){
        try{
            CSocket = new Socket(ip, port);
            out = new PrintWriter(CSocket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(CSocket.getInputStream()));
        }catch(IOException e){
                System.out.println("ERROR");
        }
    
    }
    
    
    
    public void sendMessage(String msg){ 
        
        //String Response;
        
        
        out.println(msg);  // outputs message
        

        //try{
        //    Response = in.readLine();
        //}catch(IOException e){
        //    System.out.println("ERROR");
        //}
        //System.out.println(Response);
        //return Response; 
        
    
    }

    public String receveMessage(){
        String Response = "IfYouReadThisThetryCatchIsNotWorkingHowYouIntendItTo";
        try{
            Response = in.readLine();
            
        }catch(IOException e){
            System.out.println("Error");
            
        }finally{
            System.out.println(Response);
            return Response;
        }
        
        
    }
    
    public void convosation(){  // method will keep letting you send a message untill you stop
        CClient client = new CClient();
        while (true){
            Scanner scan = new Scanner(System.in);
            System.out.println("Type QUIT to end the convosation or press any key to send a message");
            String qit = scan.nextLine();
            if("QUIT".equals(qit)){
                client.STOP();
            }
            else{
                client.sendMessage(client.Message()); // Runs the send message method with the output from the Message method
                client.receveMessage();
            }
        }       
    }

    public String Message(){                   
            Scanner scan = new Scanner(System.in); 
            System.out.println("please enter a mesasge to be sent");
            String message = scan.nextLine();
           
            return message;
        
    }
    
    public void STOP(){
        try{
            in.close();
            out.close();
            CSocket.close();
        }catch(IOException e){
                System.out.println("ERROR");
        }
    }
    
    /**
     *
     */
    public static void main(String[] args){
        CClient client = new CClient(); // Making a new client class
        client.StartConnection(client.GetAddress(), client.GetPort()); // runs the startConnection method but runs the Get address and Get port method first so the Start connection method has the IP and Port number 
        client.convosation();
        // client.STOP(); // runs the stop method which will terminate the server
    }
    
    
    
}


服务器代码:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package oserver;

import  java.net.*;
import  java.io.*;
import com.dosse.upnp.UPnP;
import java.util.Scanner;

/**
 *
 * @author sgmud
 */
public class SServer { // Server Class 
    public ServerSocket SSocket;
    public Socket CSocket;
    public PrintWriter out;
    public BufferedReader in;
    
    public int GetPort(){ // Gets port number for socket to be set listening to
        Scanner scan = new Scanner(System.in);
        System.out.println("please enter the port number");
        int PortNum = scan.nextInt();
        return PortNum;
        
    }    
    
    public void start(int port) { // Starts the server with the collected port
        try{
            System.out.println("Server Started");
            UPnP.openPortTCP(port);
            SSocket = new ServerSocket(port);
            CSocket = SSocket.accept();
            System.out.println("Server Connected");
            
            out = new PrintWriter(CSocket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(CSocket.getInputStream()));
            
            
            String input;
            while ((input = in.readLine()) != null){
                if(".".equals(input)){
                    out.println("goodbye");
                    break;
                }
                else{
                    out.println(input);
                }
            }
            
            
            
            }catch(IOException e){
                System.out.println("ERROR");
        }   
    }

    public void stop(){ // Will close all connections
        try{
            //in.close();
            out.close();
            CSocket.close();
            SSocket.close();
        }catch(IOException e){
                System.out.println("ERROR");
        }
    }

    public static void main(String[] args){
        
        SServer server = new SServer(); // Creat new server class
        server.start(server.GetPort()); // Starts the server with the port number
        
        
    }
    
    
    
    
    
    
    
}

错误(这是在客户端):

run:
Please enter the IP address of the host
0.0.0.0
please enter the port number
6666
Type QUIT to end the convosation or press any key to send a message
h
please enter a mesasge to be sent
hello
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.io.PrintWriter.println(String)" because "this.out" is null
    at oclient.CClient.sendMessage(CClient.java:54)
    at oclient.CClient.convosation(CClient.java:94)
    at oclient.CClient.main(CClient.java:125)


标签: javanetworking

解决方案


您的问题似乎不是 try-catch 而是缺少错误处理。

如果我们假设 sendMessage 中被注释掉的代码实际上是可操作的:

    try{
        Response = in.readLine();
    }catch(IOException e){
        System.out.println("ERROR");
    }
    System.out.println(Response);
    return Response; 

那么如果在“try”中执行的代码出现异常,会发生什么是你打印出错误,这就是你所做的一切。

然后执行“向下页”,您尝试打印并返回 Response 的值。但是从未分配过响应;try 块内的分配从未完成。所以 Response 仍然具有它在进入 sendMessage 时的值,它可能为 null。

如果您要在 sendMessage 中捕获错误异常,那么 (a) 您需要编写代码来处理错误,并且 (b) sendMessage 需要一种指示失败的方法。也许你让函数返回成功的响应,返回 null 的失败。然后调用者必须知道可能返回空值。

try{
    Response = in.readLine();
}catch(IOException e){
    System.out.println("ERROR");
    return null;
}
System.out.println(Response);
return Response; 

或者,您无法在此处捕获错误,但允许它传播出去。也就是说,sendMessage 的调用者必须知道 sendMessage 可以抛出异常,并且要么处理它,要么让它传播出去。决定在何处处理异常是需要在更广泛的基础上考虑的事情,而不仅仅是一种方法。

顺便说一句,Stack Overflow 上的许多帖子都通过“打印并继续”显示了相同的异常处理模式。这很少是一个好方法。


推荐阅读