Android 客戶端與PC服務(wù)端socket通信接收與發(fā)送圖片(終結(jié)者)

前言

這個(gè)解決方案是我和隊(duì)友在《物聯(lián)網(wǎng)》比賽的集訓(xùn)中得到的。在socket中Android客戶端接收?qǐng)D片是相當(dāng)?shù)募郑ǚ凑耶?dāng)時(shí)就是這樣覺得),接收文字還算簡(jiǎn)單。在剛開始接觸socket接收?qǐng)D片的時(shí)候,出現(xiàn)一大堆意想不到的結(jié)果,要么圖片顯示不出來,要么圖片顯示不完整都有可能,下面我給出自己的解決方案,如果您有幸碰到了這個(gè)問題而且正在不知道怎么解決而發(fā)愁的時(shí)候,希望這篇文章能給您一些幫助。

開車

相信你們剛開始也會(huì)像我一樣犯了這樣一個(gè)錯(cuò)誤用了下面這一段代碼處理流的接收

while((len = inputStream.read(bs))!=-1)

這段代碼并沒有錯(cuò),只是我們還不太了解socket通信的原理。
當(dāng)你在socket使用這段代碼,你將永遠(yuǎn)都接收不到數(shù)據(jù),因?yàn)閟ocket一旦通信是一直連接,所以永遠(yuǎn)得不到返回-1,除非對(duì)方斷開連接。還有在socket通信中不能隨便關(guān)閉流,否則將影響雙方的通信,要在適當(dāng)?shù)臅r(shí)候關(guān)閉流才是最佳的做法。

核心代碼

由于我寫的是簡(jiǎn)單的接收和發(fā)送,沒有其他的東西,所以我直接貼核心代碼就行,當(dāng)然我也會(huì)把源碼鏈接放在下面給大家共享。

接收?qǐng)D片

Socket socket = new Socket("192.168.162.59", 9999);
InputStream inputStream = socket.getInputStream();
//begin 圖片接收
//第1步:接收服務(wù)端發(fā)過來的圖片大小
byte[] picLenBuff = new byte[200];
int picLen = inputStream.read(picLenBuff);
//將String 轉(zhuǎn)換成 int
String picLenString = new String(picLenBuff, 0, picLen);
int getPicLen = Integer.valueOf(picLenString);
//第2步:回饋。向服務(wù)端反饋客戶端已經(jīng)接收到圖片的大小了,可以開始發(fā)圖片了
OutputStream outputStream = socket.getOutputStream();
String string = "1";
outputStream.write(string.getBytes());
outputStream.flush();
//第3步:開始接收?qǐng)D片
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 

發(fā)送圖片

Socket socket = new Socket("192.168.162.59", 9999);
OutputStream outputStream = socket.getOutputStream();
//初始化2M以內(nèi)的圖片緩存
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);
//向服務(wù)端發(fā)送圖片大小
outputStream.write(lenString.getBytes());
outputStream.flush();
//定義回饋
byte[] getRec = new byte[1];
InputStream inputStream = socket.getInputStream();
inputStream.read(getRec);
String string = new String(getRec);
//如果得到回饋是1,說明服務(wù)端已經(jīng)接收完圖片大小,可以開始發(fā)送圖片了
if(string.equals("1"))
{
    outputStream.write(PicBuff, 0, lenPic);
    outputStream.flush();
}

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

這里只要講解下接收?qǐng)D片這段代碼要注意的地方

/**********************最主要部分***********************/
while(offset < getPicLen)
{
    int len = inputStream.read(bitmapBuff, offset, getPicLen-offset);
    offset+=len;
}
/**********************最主要部分***********************/
  1. 如果PC服務(wù)端發(fā)送的圖片比較大,Android客戶端不可能一次性讀完全部輸入流,所以要在while(offset < getPicLen)中循環(huán)讀取。
  2. read函數(shù)中的第三個(gè)參數(shù)要減去偏移量,否則會(huì)出現(xiàn)圖片顯示不完整或顯示不出來等問題。
    源碼點(diǎn)擊下載
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,062評(píng)論 25 709
  • Java Socket編程 對(duì)于Java Socket編程而言,有兩個(gè)概念,一個(gè)是ServerSocket,一個(gè)是...
    天空下天的月亮閱讀 2,128評(píng)論 10 41
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,569評(píng)論 19 139
  • 捧清水似的陽光洗了臉 我行走在湖底 文字像小船懸浮,遠(yuǎn)離我 魚鱗多了青色 我的等長(zhǎng)出鰭的脈絡(luò) 而十里外空城 目睹陽...
    驚蟄夕閱讀 294評(píng)論 12 32
  • 弓身欲攬光明, 隨風(fēng)舒展風(fēng)情, 柔弱似水低問, 何故薄幸? 湖送綠柳白云!
    平天下之文世界閱讀 590評(píng)論 0 7

友情鏈接更多精彩內(nèi)容