java - 当涉及到 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)
解决方案
您的问题似乎不是 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 上的许多帖子都通过“打印并继续”显示了相同的异常处理模式。这很少是一个好方法。
推荐阅读
- javascript - 根据 div:contains 值更改数据集属性
- reactjs - 中继 11 中的“fetchQuery.toPromise()”:什么是 3D 数据?
- reactjs - Material UI 对话框组件 - 如何显示它?
- odata - OData - 一对多过滤所有没有数据的记录
- javascript - 调用 page.waitForTimeout 后,Puppeteer 无法单击元素
- python - 添加基于 pytest 的框架作为依赖项
- node.js - 如何使用node js ad mongodb制作一个针对多个国家的分类广告网站?
- python - Websocket 数据流索引
- java - Java Saxon 10.5 XSL 3 转换,未找到 href 文件
- javascript - 如何使用 Next.js 将 PNG 徽标添加到 Tailwind CSS 导航栏?