2016-11-04 8 views
1

ちょっと、このプログラムを最後の2〜3日間デバッグしようとしています。ここで問題は、私はクライアント側のサーバーアーキテクチャとすべてのクライアント(とその情報を)ソケット接続を使用して特定の時間間隔の後にサーバーを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

吊るしたクライアントを再現できません。私はストリームが完全であるか閉じる前にフラッシュされるので、後でストリームをフラッシュせずにオブジェクトをストリームに書き込む方法を行う必要があると思います。最後にブロックを使用してソケットとストリームを閉じてください。

ソースコードを書き換えて、ユーザーオブジェクト(提供されたコードにはありません)の代わりに "Hallo、Server"という文字列を送信しました。私は送信後少し遅れていました。サーバを接続で溢れさせないためです。

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(); 
    } 
} 

EDIT:System.outにオーバーラインをTCPプロトコルがTCPハンドシェイクを行うにはいくつかの時間を必要とし、サーバが出力に多少の時間がかかり、ソケットを閉じる。

java.net.BindException:既に使用中のアドレス:サーバが使用可能なポートを使い果たしているため、を1-2秒後に接続してください。 待ち時間の短いpingについては、UDPプロトコルがより良い(example code for a UDP pingerを参照)か、ソケットを開いたままにしてpingごとに再利用してください。

+0

ネットワークコードにスリープ状態を追加しても問題は解決しません。それはそれらを遅らせるだけです。 – EJP

関連する問題