2017-04-19 60 views
1

我正在爲一個項目製作一個簡單的數學服務器,但在計算結果時會遇到一些困難。我創建了數學服務器,但我知道我的問題來自客戶端。Java數學服務器 - 客戶端問題

我有4個班,數學服務:

public interface MathService { 
public double add(double firstValue, double secondValue); 
public double sub(double firstValue, double secondValue); 
public double div(double firstValue, double secondValue); 
public double mul(double firstValue, double secondValue); 
} 

PlainMathService:

public class PlainMathService implements MathService { 
public double add(double firstValue, double secondValue) { 
return firstValue+secondValue; 
} 
public double sub(double firstValue, double secondValue) { 
return firstValue-secondValue; 
} 
public double mul(double firstValue, double secondValue) { 
return firstValue * secondValue; 
} 
public double div(double firstValue, double secondValue) { 
if (secondValue != 0) 
return firstValue/secondValue; 
return Double.MAX_VALUE; 
} 
} 

MathServer

public class MathServer{ 
protected MathService mathService; 
protected Socket socket; 

public void setMathService(MathService mathService) { 
this.mathService = mathService; 
} 
public void setSocket(Socket socket) { 
this.socket = socket; 
} 
public void execute() { 
try { 
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream())); 
// read the message from client and parse the execution 
String line = reader.readLine(); 
double result = parseExecution(line); 
// write the result back to the client 
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())); 
writer.write(""+result); 
writer.newLine(); 
writer.flush(); 
// close the stream 
reader.close(); 
writer.close(); 
} 
catch (Exception e) { 
e.printStackTrace(); 
} 
} 
// the predefined protocol for the math operation is 
// operator:first value:second value 
protected double parseExecution(String line) 
throws IllegalArgumentException { 
double result = Double.MAX_VALUE; 
String [] elements = line.split(":"); 
if (elements.length != 3) 
throw new IllegalArgumentException("parsing error!"); 
double firstValue = 0; 
double secondValue = 0; 
try { 
firstValue = Double.parseDouble(elements[1]); 
secondValue = Double.parseDouble(elements[2]); 
} 
catch(Exception e) { 
throw new IllegalArgumentException("Invalid arguments!"); 
} 
switch (elements[0].charAt(0)) { 
case '+': 
result = mathService.add(firstValue, secondValue); 
break; 
case '-': 

result = mathService.sub(firstValue, secondValue); 
break; 
case '*': 
result = mathService.mul(firstValue, secondValue); 
break; 
case '/': 
result = mathService.div(firstValue, secondValue); 
break; 
default: 
throw new IllegalArgumentException("Invalid math operation!"); 
} 
return result; 
} 
public static void main(String [] args)throws Exception{ 
int port = 80; 
if (args.length == 1) { 
try { 
port = Integer.parseInt(args[0]); 
} 
catch(Exception e){ 
} 
} 
System.out.println("Math Server is running..."); 
// create a server socket and wait for client’s connection 
ServerSocket serverSocket = new ServerSocket(4444); 
Socket socket = serverSocket.accept(); 
// run a math server that talks to the client 
MathServer mathServer = new MathServer(); 
mathServer.setMathService(new PlainMathService()); 
mathServer.setSocket(socket); 
mathServer.execute(); 
System.out.println("Math Server is closed..."); 
    } 
    } 

最後,MathClient:

public class MathClient { 
public static void main(String [] args){ 
String hostname = "localhost"; 
int port = 80; 
if (args.length != 2) { 
System.out.println("Use the default setting..."); 
} 
else { 
    hostname = args[0]; 
port = Integer.parseInt(args[1]); 
} 
try { 
// create a socket 
Socket socket = new Socket(hostname, 4444); 

    // object creation handling keyboaard inputs 
    BufferedReader input = new BufferedReader(new 
InputStreamReader(System.in)); 


String Choice = "a",     // variable 
    firstValue = "45",  // 1st number 
    secondValue = "2",  // 2nd number 
    defoper = "-",  // default operation 
    strResult=""; 
    // insntiate objects needed to send/receive to/from server 
    InputStream in = socket.getInputStream(); //data read from socket 
    BufferedReader br = new BufferedReader(new InputStreamReader(in)); //add 
to buffer 
    OutputStream out = socket.getOutputStream(); //send data to socket 
    PrintWriter pr = new PrintWriter(out, true); //send text 

// operations 
while (Choice.charAt(0) != 'x') 
{ 
// ui 
System.out.println("\n\n  E(x)it from server.\n" + 
    "  Press any other key to calculate. "); 
Choice = input.readLine(); 
if (Choice.equals("")) 
    Choice = "a"; 
switch(Choice.charAt(0)) 
{ 
    case 'x': 
      pr.println("x"); 
      break; 
    default: 
      pr.println("a"); 
      System.out.print("Enter 1st integer: "); 
      firstValue = input.readLine(); 
      if (firstValue.equals("")) 
        firstValue = "12"; 
        System.out.print("Enter 2nd integer: "); 
      secondValue = input.readLine(); 
      if (secondValue.equals("")) 
        secondValue = "2000"; 
        System.out.print("Enter your operand: "); 
      defoper = input.readLine(); 
      if (defoper.equals("")) 
        defoper = "+"; 
      // send the two numbers and the operation to server 
      pr.println(firstValue); 
      pr.println(secondValue); 
      pr.println(defoper); 
// read result from server 
strResult = br.readLine(); 
System.out.println(strResult); 
      break; 
} 
} 
// close connection 
socket.close(); 
} 


catch (Exception e) { 
e.printStackTrace(); 
}}} 

問題是基本上我可以輸入第一個和第二個整數,也是操作數,但是一旦我嘗試計算這個輸入,程序就會崩潰。對於這一發現我相當陌生,它爲什麼會發生這樣的混亂,但我很確定它與客戶端有關。由於

編輯:崩潰從客戶端 輸出後:

從服務器
run: 
Use the default setting... 


    E(x)it from server. 
    Press any other key to calculate. 

Enter 1st integer: 5 

Enter 2nd integer: 1 

Enter your operand: * 

java.net.SocketException: Connection reset 
    at java.net.SocketInputStream.read(SocketInputStream.java:210) 
    at java.net.SocketInputStream.read(SocketInputStream.java:141) 
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284) 
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326) 
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) 
    at java.io.InputStreamReader.read(InputStreamReader.java:184) 
    at java.io.BufferedReader.fill(BufferedReader.java:161) 
    at java.io.BufferedReader.readLine(BufferedReader.java:324) 
    at java.io.BufferedReader.readLine(BufferedReader.java:389) 
    at mathserver.MathClient.main(MathClient.java:80) 

輸出崩潰後:

run: 
Math Server is running... 
java.lang.IllegalArgumentException: parsing error! 
Math Server is closed... 
    at mathserver.MathServer.parseExecution(MathServer.java:52) 
    at mathserver.MathServer.execute(MathServer.java:30) 
    at mathserver.MathServer.main(MathServer.java:98) 

編輯2:這裏是我試圖去適應原來的MathClient文件允許用戶輸入。 (程序100%使用此文件而不是以上MathClient)

public class MathClient { 
public static void main(String [] args){ 
String hostname = 「localhost」; 
int port = 10000; 
if (args.length != 2) { 
System.out.println(「Use the default setting...」); 
} 
else { 
hostname = args[0]; 
port = Integer.parseInt(args[1]); 
} 
try { 
// create a socket 
Socket socket = new Socket(hostname, port); 
// perform a simple math operation 「12+21」 
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())); 
writer.write(「+:12:21」); 
writer.newLine(); 
writer.flush(); 
// get the result from the server 
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream())); 
System.out.println(reader.readLine()); 
reader.close(); 
writer.close(); 
} 
catch (Exception e) { 
e.printStackTrace(); 
} 
} 
} 
+0

它碰撞了什麼錯誤?這很重要。 – Carcigenicate

+0

另外,請修復您的代碼格式。部分閱讀非常困難。 – Carcigenicate

+0

你不應該使用catch(Exception),因爲它也會捕獲RuntimeExceptions。你更明確的例外,就像IOException – ControlAltDel

回答

0

您的問題是輸入到您的服務器不是預期的。要拆分上「:」,但您不添加:你的符和操作數之間的字符,所以你Double.parseDouble調用失敗的位置:

try { 
firstValue = Double.parseDouble(elements[1]); 
secondValue = Double.parseDouble(elements[2]); 
} 
catch(Exception e) { 
throw new IllegalArgumentException("Invalid arguments!"); 
} 

這導致您的插座走出去的範圍,所以套接字關閉,並且套接字關閉導致客戶端的異常。

請注意,在很多情況下SocketExceptions不是問題,因爲此功能允許您的讀者線程擺脫其在套接字上等待的read調用。

此外,在您的服務器,在那裏你有

public void execute() { 
try { 
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream())); 
// read the message from client and parse the execution 
String line = reader.readLine(); 
double result = parseExecution(line); 
// write the result back to the client 
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())); 
writer.write(""+result); 
writer.newLine(); 
writer.flush(); 
// close the stream 
reader.close(); 
writer.close(); 

你並不需要關閉這兩個讀者和作家,如關閉任何一個都關閉基礎套接字。國際海事組織清楚地刪除這些最後兩行,只是做socket.close();

+0

感謝您花時間看看這個問題,併爲您的答案。你是否建議在每次輸入後添加冒號都會導致程序正常工作?即+:,4:,3:?對不起,如果沒有意義,即時通訊新的這一點,並發現它相當混亂atm – 944jmc

+0

不是你的例子字符串的樣子。它似乎是從你的示例字符串(刪除冒號),如果你拆分「,」而不是「:」它應該解決這個問題 – ControlAltDel

+0

改變拆分後仍然崩潰,其說話部分然後錯誤是在這段代碼://從服務器讀取結果 strResult = br.readLine(); System.out.println(strResult); 休息; – 944jmc