2016-11-04 30 views
1

嘿我試圖從最近2-3天調試這個程序。問題在於,我構建了一個客戶端服務器體系結構,並且所有客戶端在使用Socket連接的某個時間間隔後都會ping服務器(使用它們的信息)。因此,在服務器端,當我嘗試構造ObjectOutputStream時,程序卡住了。這裏是客戶端的代碼。
程序卡在ObjectInputStream的構造函數

public void pingUpdate(){ 
    Thread pingThread = new Thread() { 
    public void run() { 
     while(true) { 
      try { 
       ping_socket = new Socket("localhost", 11111); 
       ObjectOutputStream ping_objectOutputStream = new ObjectOutputStream(ping_socket.getOutputStream()); 
       ping_objectOutputStream.flush(); 

       ping_objectOutputStream.writeObject(user); 

       ping_objectOutputStream.close(); 

       ping_socket.close(); 

      }catch (Exception exception) { 
       exception.printStackTrace(); 
      } 
      } 
    }; 
    pingThread.start(); 
} 

這裏是服務器的代碼

public void run() { 
while (true) { 
     try { 

      System.out.println("Server Listening"); 

      Socket client = null; 

      client = serverSock.accept(); 
      System.out.println("Accepted"); 

      InputStream inputStream = client.getInputStream(); 

      System.out.println("Input stream established"); 

      ObjectInputStream ois = new ObjectInputStream(inputStream); 

       System.out.println("Object streams established"); 

       User user = (User) ois.readObject(); 

       System.out.println("Object read"); 

       ois.close(); 
       client.close(); 
      } 
       catch (Exception e){ 
        e.printStackTrace(); 
       } 
     } 
    } 

服務器程序打印,直到「建立輸入流」,並會被卡住。我不知道爲什麼會發生這種情況,儘管我在客戶端刷新了輸出流。謝謝。

+2

您應該創建一次流。你的'pingThread'在每個循環中創建一個新的'ObjectOutputStream'。你可能也想通過一些網絡教程,否則你會在幾個星期內進行調試。 – Kayaman

+0

如果拋出異常,則不關閉套接字。 – EJP

+0

@Kayaman在循環的每次迭代中創建ObjectOutputStream會出現什麼問題? – omjego

回答

1

我無法重現掛起的客戶端。我認爲它必須要做的是如何在不刷新流的情況下將對象寫入流,因爲只有在流完整或關閉之前纔會刷新流。請使用finally塊關閉套接字和流。

我已經重寫了您的源代碼併發送了一個字符串「Hallo,Server」而不是User對象(在您提供的代碼中缺少該對象)。發送後,我添加了一些延遲,因爲沒有連接服務器。

我已經使用JDK 1.8 Update 102測試了Win 8.1上的代碼,它現在可以工作。

客戶:

import java.io.IOException; 
import java.io.ObjectOutputStream; 
import java.net.Socket; 

public class Client{ 

    public static void main(String[] args){ 

     new Client().pingUpdate(); 
    } 

    public void pingUpdate(){ 

     Thread pingThread = new Thread(){ 

     @Override 
     public void run(){ 

      while(true){ 
       Socket ping_socket = null; 
       ObjectOutputStream ping_objectOutputStream = null; 
       try{ 
        ping_socket = new Socket("localhost", 
              11111); 
        ping_objectOutputStream = new ObjectOutputStream(ping_socket.getOutputStream()); 

        ping_objectOutputStream.writeObject("Hallo, Server"); 
        ping_objectOutputStream.flush(); 
       } 
       catch(Exception exception){ 
        exception.printStackTrace(); 
       } 
       finally{ 
        try{ 
        if (ping_objectOutputStream != null){ 
         ping_objectOutputStream.close(); 
        } 
        } 
        catch(IOException e){ 
        e.printStackTrace(); 
        } 
        try{ 
        if (ping_socket != null){ 
         ping_socket.close(); 
        } 
        } 
        catch(IOException e){ 
        e.printStackTrace(); 
        } 
       } 

       // wait some time for the next ping 
       try{ 
        Thread.sleep(1000); 
       } 
       catch(InterruptedException e){ 
        e.printStackTrace(); 
       } 
      } 
     } 
     }; 
     pingThread.start(); 
    } 
} 

服務器:

import java.io.IOException; 
import java.io.InputStream; 
import java.io.ObjectInputStream; 
import java.net.ServerSocket; 
import java.net.Socket; 

public class Server{ 

    public void servePingUpdate(){ 

     Thread pingThread = new Thread(){ 

     @Override 
     public void run(){ 

      ServerSocket serverSock = null; 
      try{ 
       serverSock = new ServerSocket(11111); 

       while(true){ 
        Socket client = null; 
        ObjectInputStream ois = null; 

        try{ 
        System.out.println("Server Listening"); 

        client = serverSock.accept(); 
        System.out.println("Accepted"); 

        InputStream inputStream = client.getInputStream(); 

        System.out.println("Input stream established"); 

        ois = new ObjectInputStream(inputStream); 

        System.out.println("Object streams established"); 

        String message = (String) ois.readObject(); 

        System.out.println("Object read: " + message); 
        } 
        catch(Exception e){ 
        e.printStackTrace(); 
        } 
        finally{ 
        try{ 
         if (ois != null){ 
          ois.close(); 
         } 
        } 
        catch(IOException e){ 
         e.printStackTrace(); 
        } 
        try{ 
         if (client != null){ 
          client.close(); 
         } 
        } 
        catch(IOException e){ 
         e.printStackTrace(); 
        } 
        } 
       } 
      } 
      catch(IOException e1){ 
       e1.printStackTrace(); 
      } 
      finally{ 
       try{ 
        if (serverSock != null){ 
        serverSock.close(); 
        } 
       } 
       catch(IOException e){ 
        e.printStackTrace(); 
       } 
      } 
     } 
     }; 
     pingThread.start(); 
    } 

    public static void main(String[] args){ 

     new Server().servePingUpdate(); 
    } 
} 

編輯:TCP協議需要一些時間做TCP握手和服務器上的System.out需要一些時間來輸出線和關閉插座。

沒有等待在客戶端拋出一個java.net.BindException:地址已經在使用:連接 1-2秒後,因爲服務器的可用端口。 對於低延遲ping通,UDP協議更好,請參閱example code for a UDP pinger或保持套接字處於打開狀態並將其重複用於每個ping。

+0

在聯網代碼中添加睡眠並不能解決它們。它只會拖延它們。 – EJP