Android-socket的基本使用,发送文字和图片以及心跳

原创 2017年07月20日 15:55:20

项目需求收集通过Socket向服务器发送图片,之前没搞过,网上搜搜写了下面的例子,勉强解决了需求。

为了测试切换着方便,所以方法写的有点碎了。。。
原文地址 http://blog.csdn.net/qq_25806863/article/details/75533109

要求发送的消息的格式是,8个字节的消息长度+消息体

这里写图片描述

因为需要8个字节,所以消息长度决定用long

如果需要4个字节,可以用int

手机客户端接收服务器的文字消息

服务端

服务端定义好端口号,开启以一个ServerSocket,写入文字消息:

public class Service {
    private static Socket socket;
  //定义端口号
    private static final int POST = 30000;

    public static void main(String[] args) {
        try {
          //发送的内容
            sendMsg("来自服务器的问候");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void sendMsg(String msg) throws IOException {
      System.out.println("开始连接");
      //创建socket服务端口是30000,并等待连接
        ServerSocket serverSocket = new ServerSocket(POST);
        Socket socket = serverSocket.accept();
      //获取输出流
        DataOutputStream out = new DataOutputStream(socket.getOutputStream());
        sendTextMsg(out, msg);
        out.close();
        socket.close();
        serverSocket.close();
      System.out.println("通讯结束");
    }

    public static void sendTextMsg(DataOutputStream out, String msg) throws IOException {
      //先写长度,就是消息体的字节数,long刚好8个字节  
        out.writeLong(msg.getBytes().length);
      //写入消息
        out.write(msg.getBytes());
    }
}

客户端,接收消息

客户端首先要跟服务器进行连接,然后才能进行通讯。

Socket连接需要网络权限:

<uses-permission android:name="android.permission.INTERNET"/>

因为属于网络通讯,所以socket连接也不能放在主线程中,否则会报错

这里写图片描述

  • 添加按钮

    在布局中加一个按钮,点击方法是receive

    <Button
      android:text="接收"
      android:layout_marginTop="50dp"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:onClick="receive"/>
  • 定义方法

    在Activity中定义方法

    因为不能再主线程中访问,所以需要子线程。这里直接new了、、

    public void receive(View view){
      new Thread(new Runnable() {
          @Override
          public void run() {
              Socket socket;
              try {
                //这里进行连接服务器,
                //host是服务器ip地址,如“192.168.2.12”
                //post是端口,上面的服务端提供的端口号是30000
                  socket = new Socket(host, post);
                //获取输入流
                  DataInputStream input = new DataInputStream(socket.getInputStream());
                //读取长度,也即是消息头,
                  long len = input.readLong();
                //创建这个长度的字节数组
                  byte[] bytes = new byte[(int)len];
                //再读取这个长度的字节数,也就是真正的消息体
                  input.read(bytes);
                //将字节数组转为String
                  String s = new String(bytes);
                  Log.i("accept", "len: "+len);
                  Log.i("accept", "msg: "+s);
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }).start();
    }

运行测试

先运行服务端,会发现程序没有一次执行完,在阻塞着等待连接

这里写图片描述

这时点击app中的接收按钮,日志中会打印接收到的信息

这里写图片描述

长度为24,消息内容为“来自服务器的问候”。

因为在utf-8中一个汉字是3个字节,所以8个汉字的消息长度是24字节。

这是看服务器端的打印:

这里写图片描述

发现服务端也正常执行完毕了。

手机客户端向服务端发送文字消息

服务端接收消息

public class Service {
    private static Socket socket;
  //定义端口号
    private static final int POST = 30000;

    public static void main(String[] args) {
        try {
          //接收消息
            getMsg();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void getMsg() throws IOException {
        System.out.println("开始连接");
        ServerSocket serverSocket = new ServerSocket(POST);
        Socket socket = serverSocket.accept();
      //获取输入流,通过这个流来读取消息
        DataInputStream input = new DataInputStream(socket.getInputStream());
      //接收文字消息
        getTextMsg(input);
        input.close();
        socket.close();
        serverSocket.close();
        System.out.println("通讯结束");
    }

    public static String getTextMsg(DataInputStream input) throws IOException {
      //一样先读长度,再根据长度读消息
        long len = input.readLong();
        System.out.println("len = " + len);
        byte[] bytes = new byte[(int) len];
        input.read(bytes);
        String msg = new String(bytes);
        System.out.println("msd = " + msg);
        return msg;
    }
}

客户端发送消息

  • 增加一个发送的按钮:
<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发送!"
        android:onClick="send"/>
  • 定义方法
public void send(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Socket socket;
                try {
                //建立连接
                    socket = new Socket(host, post);
                    //获取输出流,通过这个流发送消息
                    DataOutputStream out = new DataOutputStream(socket.getOutputStream());
                    //发送文字消息
                    sendTextMsg(out,"来自手机客户端的消息");
                    out.close();
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
public void sendTextMsg(DataOutputStream out, String msg) throws IOException {
        byte[] bytes = msg.getBytes();
        long len = bytes.length;
  //先发送长度,在发送内容
        out.writeLong(len);
        out.write(bytes);
    }

运行测试

先运行服务端,也会停留着这个界面等待连接:

这里写图片描述

然后点击客户端的发送按钮,这是服务端会变成下面这样,完成这次消息的通讯

这里写图片描述

手机客户端想服务端发送图片

服务端接收图片,并保存到本地

在上面的getMsg()方法中,将getTextMsg(input);改为getImgMsg(input);

下面是getImgMsg(input);方法:

public static void getImgMsg(DataInputStream input) throws IOException {
  //同样是先读长度
    long len = input.readLong();
    System.out.println("len = " + len);
    byte[] bytes = new byte[(int) len];
  //然后在读这个长度的字节到字节数组
    input.readFully(bytes);
  //将独到的内容保存为文件到本地
    File file = new File("/Users/xxx/" + len + ".png");
    FileOutputStream fileOutputStream = new FileOutputStream(file);
    fileOutputStream.write(bytes);
    System.out.println("ok");
}

客户端发送图片

  • 增加一个按钮:
<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="200dp"
    android:onClick="sendImg"
    android:text="发送图片" />
  • 定义方法

    public void sendImgMsg(DataOutputStream out ) throws IOException {
    //发送的图片为图标,就是安卓机器人,将bitmap转为字节数组
      Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher_round);
      ByteArrayOutputStream bout = new ByteArrayOutputStream();
      bitmap.compress(Bitmap.CompressFormat.PNG,100,bout);
    //写入字节的长度,再写入图片的字节
      long len = bout.size();
    //这里打印一下发送的长度
      Log.i("sendImgMsg", "len: "+len);
      out.writeLong(len);
      out.write(bout.toByteArray());
    }

运行测试

还是先开启服务端,服务器变成:

这里写图片描述

然后点击app的发送图片按钮,app中打印日志:

这里写图片描述

说明发送的图片的长度是11418个字节,大致换算大小是11k。

然后看服务端的日志:

这里写图片描述

接收到的长度也是11418,并且保存到了文件,

这里写图片描述

关于心跳包

上面的例子中,每发送一次之后就把链接关闭了:

out.close();
socket.close();
serverSocket.close();

心跳其实就是定期向服务端发送一个小数据,比如0.

让服务器知道这个链接还有用,不用关闭。

简单实现起来就是客户端通过一个无限循环,不停地向服务端发送消息,服务端通过一个无限循环不停地接收消息,都不关闭这个链接就行了。

服务端

public static void main(String[] args) {
        try {
          System.out.println("开始接收信息");
            ServerSocket serverSocket = new ServerSocket(POST);
            socket = serverSocket.accept();
            DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());

            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        try {
                            long len = 0;
                            len = dataInputStream.readLong();
                            System.out.println("len = " + len);
                            byte[] bytes = new byte[(int) len];
                            dataInputStream.readFully(bytes);
                            String s = new String(bytes);
                            System.out.println("data = " + s);
                        } catch (IOException e) {
                            e.printStackTrace();
                            isConnect = false;
                        }
                    }
                }
            }).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

客户端,一秒发送一次消息

try {
  //建立一次链接
    socket = new Socket(host,post);
    outputStream = new DataOutputStream(socket.getOutputStream());
    inputStream = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
    e.printStackTrace();
}
Log.i(TAG, "run: 开始循环发送发送心跳");
//一秒发送一个0,
while (true){
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    Log.i(TAG, "run: 发送心跳0");
    try {
        outputStream.writeLong("0".getBytes().length);
        outputStream.write("0".getBytes());
    } catch (IOException e) {
        e.printStackTrace();
        isConnect = false;
    }
}

运行测试

先运行服务端:

这里写图片描述

然后点击发送心跳的按钮,app的日志中打印:

这里写图片描述

在服务端的日志中可以看到:

这里写图片描述

一秒一次

android socket发送图片

传送图片,开始信息不全,修改后总算正确传输。 java 写的服务器,把读取的图片保存到本地。 public class AndroidRunable implements Runnable { ...
  • qq_29076343
  • qq_29076343
  • 2016-01-07 16:39:43
  • 1351

android客户端和java服务端之间用socket来传输图片

为研究android客户端和java服务端之间用socket来传输图片的问题,困扰我很久,网上的参考内容不是完整,就是不详细,所以鉴于自己的痛苦,测试成功后,我决定把代码共享,希望遇到这个问题的同胞,...
  • qingzi635533
  • qingzi635533
  • 2013-05-22 17:00:30
  • 28362

Android网络:由手机与手机WIFI互传照片谈Android TCP Socket开发要点

本文背景:局域网内手机与手机利用wifi建立tcp连接,通过socket互传照片。即一个手机当作服务器,另一个手机是客户端,客户端可以看到服务器指定文件夹内的图片缩略图,并选择下载到本机。另外,客户端...
  • yanzi1225627
  • yanzi1225627
  • 2014-03-23 13:59:18
  • 23808

Android:这是一份很详细的Socket使用攻略

前言 Socket的使用在Android的网络编程中非常重要 今天我将带大家全面了解Socket及其使用方法 目录1.网络基础1.1 计算机网络分层计算机网络分为五层:物理层、数据链路层、网络层、运输...
  • carson_ho
  • carson_ho
  • 2016-11-27 21:09:26
  • 38817

Android使用Socket(Tcp/Udp)协议进行数据传输(传输大文件)

Socket是什么:所谓Socket 通常也称作”套接字”,用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过”套接字”向网络发出请求或者应答网络请求。Socket内部又有两种协议(Tcp/...
  • a_zhon
  • a_zhon
  • 2016-08-31 13:38:40
  • 1452

Android Socket 轻松建立连接和发送消息

1.建立Socket连接         1) Socket 实现了TCP/IP协议,可以连接到网络上的上脑,并收发数据         2) ServerSocket 用于服务端...
  • wanxuedong
  • wanxuedong
  • 2017-02-04 19:12:26
  • 6408

Android蓝牙socket实现视频实时传输,以及图片和文本传输

目标 - 两台手机设备之间能够正常进行蓝牙配对(蓝牙模块儿和硬件挂钩,所以需要两台真机) - socket实现蓝牙文本传输 - 实现图片传输 - 实现实时视频传输 ##蓝牙传输注意事项 - Blu...
  • m0_37781149
  • m0_37781149
  • 2017-10-30 19:35:55
  • 260

(高效开发)Android手机间使用socket进行文件互传实例

说明这是一个Android手机间文件传输的例子,两个手机同时装上此app,然后输入接收端的ip,选择文件,可以多选,点确定,就发送到另一个手机,一个简单快捷文件快传实例。可以直接运用到项目中。 ...
  • yuankundong
  • yuankundong
  • 2016-05-24 14:28:33
  • 7304

android socket传送图片

  • 2014年07月08日 21:50
  • 7KB
  • 下载

Android中使用webSocket实现文字及单张图片发送聊天功能

WebSocket 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在 TCP 之上,同 HTTP 一样通过 TCP 来传输数据,但是...
  • lijinweii
  • lijinweii
  • 2017-06-21 17:41:34
  • 361
收藏助手
不良信息举报
您举报文章:Android-socket的基本使用,发送文字和图片以及心跳
举报原因:
原因补充:

(最多只允许输入30个字)