Android 客户端与PC服务端socket通信接收与发送图片(终结者)原创
# 前言
这个解决方案是我和队友在《物联网》比赛的集训中得到的。在socket中Android客户端接收图片是相当的棘手(反正我当时就是这样觉得),接收文字还算简单。在刚开始接触socket接收图片的时候,出现一大堆意想不到的结果,要么图片显示不出来,要么图片显示不完整都有可能,下面我给出自己的解决方案,如果您有幸碰到了这个问题而且正在不知道怎么解决而发愁的时候,希望这篇文章能给您一些帮助。
# 开车
相信你们刚开始也会像我一样犯了这样一个错误用了下面这一段代码处理流的接收
while((len = inputStream.read(bs))!=-1)
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 发送图片
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();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
以上通信格式都需要事先和PC端说好,否则通信失败。
这里只要讲解下接收图片这段代码要注意的地方
/**********************最主要部分***********************/
while(offset < getPicLen)
{
int len = inputStream.read(bitmapBuff, offset, getPicLen-offset);
offset+=len;
}
/**********************最主要部分***********************/
1
2
3
4
5
6
7
2
3
4
5
6
7
- 如果PC服务端发送的图片比较大,Android客户端不可能一次性读完全部输入流,所以要在
while(offset < getPicLen)
中循环读取。 read
函数中的第三个参数要减去偏移量,否则会出现图片显示不完整或显示不出来等问题。