上一篇https://blog.csdn.net/Haienzi/article/details/79808077介紹了java服務器端的相關操作。這一篇主要向大家介紹Android客戶端的相關實現步驟。
基本步驟:
- 用服務器端的IP地址和端口號實例化Socket對象。
- 調用connect方法,連接到服務器上。
- 將要發送到服務器的IO流填充到IO對象中,比如DataInputStream,DataOutputStrwam。
- 調用Socket提供的getInputStream和getOutputStream方法,通過IO流對象,向服務器發送數據流。
- 通訊完畢後,關閉打開的IO對象和Socket.
客戶端說明
客戶端涉及多個頁面,都要和服務器進行通信,可以寫一個消息監聽接口,用於監聽服務器端傳遞的消息。(這個監聽接口很重要,下面會詳細說明)
- MessageListener.java
/**
* 消息監聽接口
* Created by mqh on 2017/10/30.
*/
public interface MessageListener {
public void Message(String msg);
}
- Client.java
import java.net.Socket;
public class Client {
private int port;//端口號
private String address = null;//地址
private Socket mSocket;//Socket對象
private ClientThread clientThread;//客戶端線程
public void setSocket(Socket socket) {
this.mSocket = socket;
}
public Client()
{}
public Client(String ip,int port)
{
this.address = ip;
this.port = port;
}
public boolean start() {
try {
//實例化socket對象
mSocket = new Socket(address,port);
Log.d("testServer","client start,ip:"+address+",port:"+port);
if (mSocket.isConnected()) {
System.out.println("Connected..");
//開啓對應的客戶端線程
clientThread = new ClientThread(mSocket);
clientThread.start();
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
// 直接通過client得到讀線程
public ClientInputThread getClientInputThread() {
return clientThread.getIn();
}
// 直接通過client得到寫線程
public ClientOutputThread getClientOutputThread() {
return clientThread.getOut();
}
// 直接通過client停止讀寫消息
public void setIsStart(boolean isStart) {
clientThread.getIn().setStart(isStart);
clientThread.getOut().setStart(isStart);
}
public class ClientThread extends Thread {
private ClientInputThread in;//讀線程
private ClientOutputThread out;//寫線程
public ClientThread(Socket socket) {
in = new ClientInputThread(socket);
out = new ClientOutputThread(socket);
}
//開啓讀線程和寫線程
public void run() {
in.setStart(true);
out.setStart(true);
in.start();
out.start();
}
// 得到讀消息線程
public ClientInputThread getIn() {
return in;
}
// 得到寫消息線程
public ClientOutputThread getOut() {
return out;
}
}
}
- ClientInputThread.java
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
* Created by mqh on 2017/10/30.
*/
public class ClientInputThread extends Thread {
private Socket mSocket;
private boolean isStart = true;
private DataInputStream inputStream;// 對象輸入流
private InputStreamReader iReader;
private String msg;
private MessageListener mMessageListener;//消息監聽接口
public ClientInputThread(Socket socket)
{
this.mSocket = socket;
try{
inputStream = new DataInputStream(socket.getInputStream());// 實例化數據輸入流
}catch (IOException e)
{
e.printStackTrace();
}
}
//設置消息監聽對象
public void setMessageListener(MessageListener messageListener)
{
this.mMessageListener = messageListener;
}
public void setStart(Boolean isStart)
{
this.isStart = isStart;
}
@Override
public void run() {
try {
System.out.println("Input isStart: " + isStart);
while (isStart) {
//接收從服務器發送過來的消息
iReader = new InputStreamReader(inputStream, "UTF-8");
//緩衝數組
char[] buffer = new char[1024];
int count = 0;
StringBuffer sBuilder = new StringBuffer();
while ((count = iReader.read(buffer,0,buffer.length))>-1) {
sBuilder.append(buffer,0,count);
if(count<1024)
{
break;
}
}
//將消息傳遞給監聽器 (發送給需要的頁面)
mMessageListener.Message(sBuilder.toString());
}
if(inputStream !=null)
{
inputStream.close();
}
if (mSocket != null)
mSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- ClientOutputThread.java
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
/**
* Created by mqh on 2017/10/30.
*/
public class ClientOutputThread extends Thread {
private Socket socket;
private DataOutputStream dataOutputStream;
private OutputStreamWriter oStreamWriter;
private boolean isStart = true;
private String msg;//發送給服務器的消息
public ClientOutputThread(Socket socket) {
this.socket = socket;
try {
dataOutputStream = new DataOutputStream(socket.getOutputStream());// 在構造器裏面實例化對象輸出流
} catch (IOException e) {
e.printStackTrace();
}
}
public void setStart(boolean isStart) {
this.isStart = isStart;
}
// 這裏處理跟服務器是一樣的 設置發送給服務器的消息
public void setMsg(String msg) {
this.msg = msg;
synchronized (this) {
notify();
}
}
@Override
public void run() {
try {
while (isStart) {
if (msg != null) {
if (socket == null)
return;
//構建輸出流對象
oStreamWriter = new OutputStreamWriter(dataOutputStream, "UTF-8");
StringBuffer sBuilder = new StringBuffer();
sBuilder.append(msg);
//將消息發送給服務器
oStreamWriter.write(sBuilder.toString());
oStreamWriter.flush();
synchronized (this) {
wait();// 發送完消息後,線程進入等待狀態
}
}
}
if(oStreamWriter != null)
{
oStreamWriter.close();
}
if (dataOutputStream != null)// 循環結束後,關閉流,釋放資源
dataOutputStream.close();
// 循環結束後,關閉輸出流和socket
if (socket != null)
socket.close();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
而且Android客戶端在用戶已經登陸的情況下需要一直向服務器傳遞消息,所以,想要保持與服務器的長連接,可以通過創建後臺服務來實現。當應用打開時,開啓後臺服務,在後臺服務中發送和接收與服務器通信的消息,它不會因爲界面的切換,應用程序的切換而輕易中斷。