Android和服务端通过Socket收发文字图片的实现
今天总结一下Android客户端和服务端通过Socket收发文字和图片的实现方式:
关于网络通信的基础知识这边就不赘述了,网上多的是,今天主要写一下实现的部分:
简单的描述Sokcket的通信主要有一下几步:
1、服务端实例化一个ServerSocket端口监听类,并将要开启的端口作为参数传入
2、通过ServerSocket.accept()方法监听客户端连接,当有客户端连接即创建一个本次连接的Socket对象
3、打开服务端生成的Socekt的输入输出流,进行数据收发
4、客户端通过服务端的IP和端口号创建一个连接Socket,并发起连接请求
5、连接成功后打开客户端的输入输出流进行数据收发。
主要流程如下图所述:
Android的UI主进程不允许进行任何耗时操作,耗时操作必须放在线程内进行,网络通信就是耗时操作的一种,所以需要开线程实现网络通信
界面预览:
界面就不多加讲解了,简单的布局直接上代码:
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="30dp"
android:textSize="18sp"
android:background="#FFF"
android:hint="输入发送的文字"
android:id="@+id/et_send"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="发送并接收"
android:onClick="sendandreceive"/>
<TextView
android:layout_width="match_parent"
android:layout_height="30dp"
android:id="@+id/tv_receive"
android:background="#FFF"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="接收图片"
android:onClick="receiveImg"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/img_receive"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="选择图片"
android:onClick="selectImg"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="发送图片"
android:onClick="sendImg"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/img_send"/>
</LinearLayout>
</ScrollView>
收发文字:
客户端:
1、获取发送数据
2、开启线程单独通信
3、通过IP和端口号30001请求连接
4、打开输入输出流
5、通过OutputStream.write()方法发送数据,注意加上"\r\n"表示换行,因为服务端接受时按行接收,需要换行标识符
6、通过BufferedReader.readLine()等待接收数据,按行读取数据
/** * 发送接收文字 * @param view */ public void sendandreceive(View view) { final String sendMessage = et_send.getText().toString(); if(sendMessage.equals("")) { Toast.makeText(Main.this, "发送信息不能为空", Toast.LENGTH_SHORT).show(); } else { new Thread() { public void run() { try { Socket s = new Socket(Config.IP, 30001); BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); OutputStream os = s.getOutputStream(); os.write((sendMessage + "\r\n").getBytes()); String content = ""; while((content = br.readLine())!=null) { Message msg = new Message(); msg.what = 0x001; msg.obj = content; handler.sendMessage(msg); } } catch (IOException e) { e.printStackTrace(); } } }.start(); } }
服务端:
1、打开30001端口监听客户端连接请求
2、打开输入输出流
3、通过BufferedReader.readLine()方法接收客户端数据
4、通过OutputStream.write()方法向客户端回写数据
/** * 收发文字 */ new Thread() { public void run() { try { ServerSocket ss = new ServerSocket(30001); while(true) { final Socket s = ss.accept(); System.out.println("连接了30001"); new Thread() { public void run() { try { BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); OutputStream os = s.getOutputStream(); String content = ""; while((content = br.readLine())!=null) { System.out.println("客户端:" + content); os.write(("我收到了你的消息:" + content + "\r\n").getBytes()); } os.close(); br.close(); s.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }.start(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }.start();
收发图片:
客户端向服务端发送:
1、通过IP和30003端口连接服务端
2、将图片Bitmap转换成字节数组
3、通过OutputStream.write()发送
/** * 发送图片 * @param view */ public void sendImg(View view) { if(bit_send == null) { Toast.makeText(Main.this, "清闲选择要发送的图片", Toast.LENGTH_SHORT).show(); } else { new Thread() { public void run() { try { Socket s = new Socket(Config.IP, 30003); OutputStream os = s.getOutputStream(); //将图片bitmap转换成字节数组 ByteArrayOutputStream baos = new ByteArrayOutputStream(); bit_send.compress(Bitmap.CompressFormat.JPEG, 100, baos); byte[] data = baos.toByteArray(); os.write(data); os.flush();//刷新缓冲区 os.close(); Message msg = new Message(); msg.what = 0x003; handler.sendMessage(msg); } catch (IOException e) { e.printStackTrace(); } } }.start(); } }
服务端接收客户端的图片:
1、打开30003端口等待客户端连接
2、打开输入流DataInputStream
3、通过DataInoputStream.read()方法获取图片数据
4、通过FileOutputStream将图片数据写入文件
/** * 接收图片 */ new Thread() { public void run() { try { ServerSocket ss = new ServerSocket(30003); while(true) { final Socket s = ss.accept(); System.out.println("链接30003"); byte[] inputByte = null; int length = 0; DataInputStream dis = new DataInputStream(s.getInputStream()); String createtime = (new Date()).getTime() +""; String url = "./"+createtime+".jpg"; FileOutputStream fos = new FileOutputStream(new File(url)); inputByte = new byte[1024]; System.out.println("开始接收数据..."); while ((length = dis.read(inputByte, 0, inputByte.length)) > 0) { System.out.println(length); fos.write(inputByte, 0, length); fos.flush(); } fos.close(); System.out.println("完成接收"); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }.start();
服务端向客户端发送图片:
1、打开端口30002等待客户端连接
2、打开DataOutputStream输出流
3、通过FileInputStream将图片数据读入字节数组中
4、将字节数组长度发送给客户端
5、通过DataInputStream.write()将图片字节数组发送给客户端
/** * 发送图片 */ new Thread() { public void run() { try { ServerSocket server = new ServerSocket(30002); while(true) { Socket socket = server.accept(); System.out.println("连接了30002"); DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); FileInputStream fis = new FileInputStream("./testImg.jpg"); int size = fis.available(); byte[] data = new byte[size]; fis.read(data); dos.writeInt(size); dos.write(data); dos.flush(); fis.close(); } } catch (IOException e) { e.printStackTrace(); } } }.start();
客户端接收服务端图片:
1、通过IP和30002端口连接服务端
2、打开客户端DataInputStream输入流
3、接收图片字节数组长度
4、接收图片字节数组
5、将字节数组转换成Bitmap
6、将Bitmap通过消息机制传递给主线程展示在界面上
/** * 接收图片 * @param view */ public void receiveImg(View view) { new Thread() { public void run() { try { Socket socket = new Socket(Config.IP, 30002); DataInputStream dataInput = new DataInputStream(socket.getInputStream()); int size = dataInput.readInt(); byte[] data = new byte[size]; int len = 0; while (len < size) { len += dataInput.read(data, len, size - len); } ByteArrayOutputStream outPut = new ByteArrayOutputStream(); Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length); bmp.compress(Bitmap.CompressFormat.PNG, 100, outPut); socket.close(); Message msg = new Message(); msg.what = 0x002; msg.obj = bmp; handler.sendMessage(msg); } catch (IOException e) { e.printStackTrace(); } } }.start(); }
最后有需要的朋友可以下载demo看看:Android客户端和服务端通过Socket收发文字和图片