Android Socket 通讯

Android socket 通讯

安卓编写Socket客户端,实现链接Socket服务端通讯。java

建立Socket链接并获取服务端数据

先建立几个全局变量吧android

private BufferedWriter writer = null;
Socket socket;

建立Socketjson

// 填好IPV4的IP地址和端口,服务端会提供,问服务端要
                socket = new Socket("192.168.1.156", 1234);
                // 下面三句照抄就行
                writer = new BufferedWriter(new OutputStreamWriter(
                        socket.getOutputStream()));
                InputStream inputStream = socket.getInputStream();
                DataInputStream input = new DataInputStream(inputStream);
                // 建立一个字节数组用来接收服务端发来的字节流,多大本身说了算
                byte[] b = new byte[100000];
                // 写一个死循环,不停的接收服务端发来的数据
                while (true) {
                    // 将数据读入字节数组,返回长度
                    int length = input.read(b);
                    // 若是服务端没发数据就return不在往下执行,继续读数据
                    if (length <= 0) return;
                    // 若是服务端发的数据不为空,则把字节数组转成字符串
                    msg = new String(b, 0, length, "gb2312");
                    // 后边就能够调用数据解析的方法
                    ....
                }

通常的通信格式都是Json的,查一下把json格式的字符串转换成json对象而后根据key值获取value的代码:数组

// 其中,data是json格式的字符串,转换成了jsonObject对象
JSONObject jsonObject = new JSONObject(data);
// 获取jsonObject对象的device_id值,固然device_id是String类型的,若是是int就用int
String i = jsonObject.getString("device_id");

发送数据给服务端

发送数据给服务端的前提是已经完成了Socket链接网络

// 首先判断一下socket是否是已经建立链接了,若是没有就无论它
if (socket == null) return;
// str是准备发给服务端的字符串
writer.write(str);
// 发出去(留坑,继续看完)
writer.flush();

这就完成了Android编写Socket与服务端通讯的功能。可是这个Socket IPV4的地址能够,IPV6的地址我没试过,据说好像有点问题,可是大部分都用IPV4,若是真的用到IPV6的话,再百度!socket

纠错

问题来咯!!!
我遇到的大坑!
在很早以前我开发的时候上面的操做编写方式彻底没问题!
可是,昨天我写的时候发现会报错!报错在 writer.flush() 这个地方。
百度以后发现:
老版的android不会有问题,可是新版本的android(好像是sdk10以上)已经不容许在UI线程(主线程)中发起网络请求了,会抛出NetWorkInUIThreadException。
因此说给服务端发送数据的时候须要写到子线程里。ide

new Thread(new Runnable() {
            @Override
            public void run() {
                // 首先判断一下socket是否是已经建立链接了,若是没有就无论它
                if (socket == null) return;
                // str是准备发给服务端的字符串
                writer.write("我是Android客户端发的数据");
                // 发出去
                writer.flush();
            }
        }).start();

这样就开一个子线程,在子线程中编写发送数据的代码或调用发送数据的方法就没问题了!this

留坑!

生命不息,留坑不止!!
若是咱们把发送数据的代码封装成一个方法,而且发送的数据须要方法传参,好比:线程

public void sendData(String str){
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 首先判断一下socket是否是已经建立链接了,若是没有就无论它
                if (socket == null) return;
                // str是准备发给服务端的字符串,会报错,传进来的参数子线程进不来
                writer.write(str);
                // 发出去
                writer.flush();
            }
        }).start();
}

发现父线程传进的参数,子线程读不到,我郁闷了很久,本身写了个内部类解决了。code

/**
     * 接口类,实现主线程向子线程传值
     */
    class sendData implements Runnable {
        String str;
        public sendValueToServer(String str) {
            this.str = str;
        }
        @Override
        public void run() {
            try {
                // 若是socket链接失败,则中止执行
                if (socket == null) return;
                // 发送传进来的值
                writer.write(str);
                // 发出去
                writer.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

而后在须要发送的地方写:

new Thread(new sendData ("传值数据")).start();

完成!哈哈哈,刺激!

相关文章
相关标签/搜索