2016-04-06 28 views
3

私のプロジェクトには、クライアントのためにサーバがあり、サービスを提供しています。クライアントが切断した後にサーバがメッセージを受信する

サーバ----主

ss = new ServerSocket(12345); 
    System.out.println("Server started.."); 
    while(true) 
    { 
     System.out.println("Waiting For clients..."); 
     Socket client = ss.accept(); 
     System.out.println("Got client..."); 
     Thread t = new Thread(new Handler(client)); 
     t.start(); 
     //exe.execute(new Handler(client)); 

    } 

これはメインメソッドであり、サーバは、着信接続を受け入れる無限ループ(スレッド)を作成します。接続が受信されると、サーバーは引数として接続したクライアントを受け取る新しいHandlerオブジェクトを作成します。このクラスで

Handlerクラス

public class Handler implements Runnable { 

    Socket client; 

    public Handler(Socket client) { 
     // TODO Auto-generated method stub 
     this.client = client; 
    } 
    @Override 
    public void run() { 
     // TODO Auto-generated method stub 
     //streams 
     try { 
      OutputStream out = client.getOutputStream(); 
      PrintWriter writer = new PrintWriter(out); 

      InputStream in = client.getInputStream(); 
      BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 

      String s = null; 

      while((s=reader.readLine())!=null) 
      { 

       //will switch on string or convert to json object 
       System.out.println("Recieved: " + s); 
      } 
      writer.close(); 
      reader.close(); 
      client.close(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 

} 

主な目的は、クライアントのリクエストを処理することです。したがって、コンストラクタはインスタンスを所有するソケットオブジェクトを初期化します。

runメソッドでオブジェクトがインスタンス化され、クライアントからの着信メッセージを印刷すると思われる無限ループがあります。

クライアントが切断するとループが壊れ、close() メソッドが呼び出され、正常にリソースを閉じて解放します。これでスレッドが終了します。

クライアント - (アンドロイド)私は、Android Studioで演奏

public class MainActivity extends AppCompatActivity { 

    final String ip = "192.168.0.18"; 
    final int port = 12345; 
    Socket client; 
    OutputStream out; 
    PrintWriter writer; 

    InputStream in; 
    BufferedReader reader; 
    final String TAG = "Debug: "; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     new ConnectToServer().execute(); 
     new SendToServer().execute(); 


    } 

    class ConnectToServer extends AsyncTask<Void, Void, Void> 
    { 

     @Override 
     protected Void doInBackground(Void... params) 
     { 
      try { 
       client = new Socket(ip,port); 
       //Log.d(TAG, "doInBackground: connected to server"); 
       //set streams 
       out = client.getOutputStream(); 
       writer = new PrintWriter(out); 

       in = client.getInputStream(); 
       reader = new BufferedReader(new InputStreamReader(in)); 

       Log.d(TAG, "doInBackground: Sent"); 



      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      return null; 
     } 
    } 
    class SendToServer extends AsyncTask<Void, Void, Void> 
    { 

     @Override 
     protected Void doInBackground(Void... params) { 
      writer.write("lol"); 
      writer.flush(); 
      return null; 
     } 
    } 

} 

前回は、前年同期のか、そうだった、と私は、ネットワーク/ IO操作は、メインスレッド上で実行することが可能であったことを非常に肯定的です。しかし、ゴールデンルールは、メインスレッドをブロックしないことを意味し、いくつかのブロッキング方法があります。

Threadクラスをカプセル化しているので、私はAsyncTaskインターフェイスを使用することを選択しました(私のライフサイクルを理解しやすくする/理解すること)。

ConnectToServerクラスは正常にサーバーに接続しますが、SendToServerクラスが呼び出されると、サーバーはメッセージを受信しません。

クライアントを切断すると(アプリケーションを終了すると)、サーバーはメッセージを出力します。

クライアントが切断した後にサーバーがメッセージを受信するのはなぜですか?

+0

なぜ2つの非同期タスクがありますか? – Pooya

+0

@Pooya私の理解から、私は接続を閉じることはありません。 Androidクライアントがアプリケーションを終了すると、接続は終了します。アプリケーションが終了すると、0または-1がサーバーに返され、BufferedReaderオブジェクトはこれを読み取り、ループから抜け出し、ストリームとソケットを閉じます。 – Moynul

+0

@Pooya One AsyncTaskはサーバーに接続するためのもので、別のAsynTaskはサーバーにデータを送信するものです。 – Moynul

答えて

1

あなたは行を読んでいますが、行は書いていません。送信されるメッセージに改行記号を追加するか、write()の代わりにprintln()を使用してください。

+0

あなたは私がサーバー上にある行を読んでいると言います。 BufferedReaderオブジェクトはreadLine()メソッドを使用して、受信パケットを読み込みます。 printLn()メソッドを使用しても、「送信されるメッセージにラインターミネーターを追加する」という意味は理解できませんでした。私はなぜ '書き込み'メソッドが実装されたのか分かりません。私はAPIのドキュメントを見ていきます。 – Moynul

+0

'readLine()'と呼ばれるメソッドが何を期待しているのか分かりませんが、それはエラーを返して行を読み込みます。 '' \ r \ n ''、 '\ r' '、' '\ n ''、または 'System.lineSeparator()'です。 'println(('行終端文字を追加します。これはすべてJavadocにあります。 – EJP

関連する問題