Android 客戶端與PC服務端socket通訊接收與傳送圖片(終結者)

JJ_Xzhi發表於2017-12-02

前言

這個解決方案是我和隊友在《物聯網》比賽的集訓中得到的。在socket中Android客戶端接收圖片是相當的棘手(反正我當時就是這樣覺得),接收文字還算簡單。在剛開始接觸socket接收圖片的時候,出現一大堆意想不到的結果,要麼圖片顯示不出來,要麼圖片顯示不完整都有可能,下面我給出自己的解決方案,如果您有幸碰到了這個問題而且正在不知道怎麼解決而發愁的時候,希望這篇文章能給您一些幫助。

開車

相信你們剛開始也會像我一樣犯了這樣一個錯誤用了下面這一段程式碼處理流的接收

while((len = inputStream.read(bs))!=-1)
複製程式碼

這段程式碼並沒有錯,只是我們還不太瞭解socket通訊的原理。 當你在socket使用這段程式碼,你將永遠都接收不到資料,因為socket一旦通訊是一直連線,所以永遠得不到返回-1,除非對方斷開連線。還有在socket通訊中不能隨便關閉流,否則將影響雙方的通訊,要在適當的時候關閉流才是最佳的做法。

核心程式碼

由於我寫的是簡單的接收和傳送,沒有其他的東西,所以我直接貼核心程式碼就行,當然我也會把原始碼連結放在下面給大家共享。

接收圖片

Socket socket = new Socket("192.168.162.59", 9999);
InputStream inputStream = socket.getInputStream();
//begin 圖片接收
//第1步:接收服務端發過來的圖片大小
byte[] picLenBuff = new byte[200];
int picLen = inputStream.read(picLenBuff);
//將String 轉換成 int
String picLenString = new String(picLenBuff, 0, picLen);
int getPicLen = Integer.valueOf(picLenString);
//第2步:回饋。向服務端反饋客戶端已經接收到圖片的大小了,可以開始發圖片了
OutputStream outputStream = socket.getOutputStream();
String string = "1";
outputStream.write(string.getBytes());
outputStream.flush();
//第3步:開始接收圖片
int offset = 0;//定義偏移量
byte[] bitmapBuff = new byte[getPicLen];//初始化圖片快取

/**********************最主要部分***********************/
while(offset < getPicLen)
{
	int len = inputStream.read(bitmapBuff, offset, getPicLen-offset);
	offset+=len;
}
/**********************最主要部分***********************/

//開始圖片解碼
Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapBuff, 0, offset);
//用handler通知UI執行緒顯示圖片
Message message = handler.obtainMessage(1, bitmap);
handler.sendMessage(message);
//end 

複製程式碼

傳送圖片

Socket socket = new Socket("192.168.162.59", 9999);
OutputStream outputStream = socket.getOutputStream();
//初始化2M以內的圖片快取
byte[] PicBuff = new byte[1024*1024*2];
FileInputStream fileInputStream = new FileInputStream(Environment.getExternalStorageDirectory()+"/20.png");
//得到圖片大小
int lenPic = fileInputStream.read(PicBuff);
String lenString = String.valueOf(lenPic);
//向服務端傳送圖片大小
outputStream.write(lenString.getBytes());
outputStream.flush();
//定義回饋
byte[] getRec = new byte[1];
InputStream inputStream = socket.getInputStream();
inputStream.read(getRec);
String string = new String(getRec);
//如果得到回饋是1,說明服務端已經接收完圖片大小,可以開始傳送圖片了
if(string.equals("1"))
{
	outputStream.write(PicBuff, 0, lenPic);
	outputStream.flush();
}
複製程式碼

以上通訊格式都需要事先和PC端說好,否則通訊失敗。

這裡只要講解下接收圖片這段程式碼要注意的地方

/**********************最主要部分***********************/
while(offset < getPicLen)
{
	int len = inputStream.read(bitmapBuff, offset, getPicLen-offset);
	offset+=len;
}
/**********************最主要部分***********************/
複製程式碼
  1. 如果PC服務端傳送的圖片比較大,Android客戶端不可能一次性讀完全部輸入流,所以要在while(offset < getPicLen)中迴圈讀取。
  2. read函式中的第三個引數要減去偏移量,否則會出現圖片顯示不完整或顯示不出來等問題。 原始碼點選下載

相關文章