在我的項目中,有一臺服務器爲客戶端服務併爲其提供服務。服務器在客戶端斷開連接後收到消息
服務器----主
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對象,該對象將連接的客戶端作爲參數。
處理程序類
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方法中實例化對象,然後有一個無限循環,假設打印來自客戶端的任何傳入消息。
當客戶端斷開連接時,循環將中斷,並且這是調用方法的地方,以正常關閉和釋放資源。由此線程結束。
客戶 - (安卓)
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;
}
}
}
我最後一次與Android Studio中扮演一年前左右,我非常積極的網絡/ IO操作都可以對主線程上運行。但是黃金法則意味着不阻塞主線程,並且有一些阻塞方法。
我選擇使用AsyncTask
接口,因爲它封裝了更低層次的Thread
類(更易於使用/瞭解我的生命週期)。
ConnectToServer
類成功連接到服務器,但一旦調用SendToServer
類,服務器就不會收到消息。
一旦我斷開客戶端(終止應用程序),服務器將打印出消息。
爲什麼服務器在客戶端斷開連接後收到消息?
爲什麼你有兩個異步任務? – Pooya
@Pooya從我的理解,我沒有關閉連接。當Android客戶端終止應用程序時,連接關閉。當應用程序關閉時,它將向服務器返回一個0或-1,並且BufferedReader對象將讀取並跳出循環,然後關閉流和套接字。 – Moynul
@Pooya一個AsyncTask用於連接服務器,另一個AsynTask是將數據發送到服務器。 – Moynul