私のプロジェクトには、クライアントのためにサーバがあり、サービスを提供しています。クライアントが切断した後にサーバがメッセージを受信する
サーバ----主
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
クラスが呼び出されると、サーバーはメッセージを受信しません。
クライアントを切断すると(アプリケーションを終了すると)、サーバーはメッセージを出力します。
クライアントが切断した後にサーバーがメッセージを受信するのはなぜですか?
なぜ2つの非同期タスクがありますか? – Pooya
@Pooya私の理解から、私は接続を閉じることはありません。 Androidクライアントがアプリケーションを終了すると、接続は終了します。アプリケーションが終了すると、0または-1がサーバーに返され、BufferedReaderオブジェクトはこれを読み取り、ループから抜け出し、ストリームとソケットを閉じます。 – Moynul
@Pooya One AsyncTaskはサーバーに接続するためのもので、別のAsynTaskはサーバーにデータを送信するものです。 – Moynul