Android 通过Socket 和服务器通讯

来源:互联网 发布:网络缓存文件夹在哪里 编辑:程序博客网 时间:2024/06/03 14:51

Android 通过Socket 和服务器通讯,是一种比较常用的通讯方式,时间比较紧,说下大致的思路,希望能帮到使用socket 进行通信的人

(1)开启一个线程发送消息    SocketOutputThread

      消息是放在队列里的,当有消息后,进入队列,线程唤醒,发送消息,并反馈发送是否成功的回调

 

(2)开启一个线程接受服务器消息 SocketInputThread

       为了防止一直收数据,浪费电池的电,采用NIO的方式读socket的数据,这个是本文的关键

 

(3)开启一个线程,做心跳,防止socket连接终断 , SocketHeartThread

 

 

(4)构建 SocketThreadManager对以上三个thread进行管理

 

(5)构建 TCPClient 发送socket消息

     在NIO的方式实现TCP,特别是在接收服务器的数据,不用写个线程定时去读了。

 

 本文地址(http://www.cnblogs.com/likwo/p/3641135.html)

 

DEMO 截图

 

主要代码如下,详细代码在附件里。

 

SocketOutPutThread 类

复制代码
package com.example.socketblockdemo;import java.io.IOException;import java.io.ObjectOutputStream;import java.net.Socket;import java.util.List;import java.util.concurrent.CopyOnWriteArrayList;import android.os.Bundle;import android.os.Handler;import android.os.Message;/** * 客户端写消息线程 *  * @author way *  */public class SocketOutputThread extends Thread{    private boolean isStart = true;    private static String tag = "socketOutputThread";    private List<MsgEntity> sendMsgList;        public SocketOutputThread( )    {        sendMsgList = new CopyOnWriteArrayList<MsgEntity>();    }        public void setStart(boolean isStart)    {        this.isStart = isStart;        synchronized (this)        {            notify();        }    }    // 使用socket发送消息    public boolean sendMsg(byte[] msg) throws Exception    {                                if (msg == null)        {            CLog.e(tag, "sendMsg is null");            return false;        }                try        {            TCPClient.instance().sendMsg(msg);                    } catch (Exception e)        {            throw (e);        }                return true;    }        // 使用socket发送消息    public void addMsgToSendList(MsgEntity msg)     {        synchronized (this)        {            this.sendMsgList.add(msg);            notify();        }    }        @Override    public void run()    {        while (isStart)        {            // 锁发送list            synchronized (sendMsgList)            {                // 发送消息                for (MsgEntity msg : sendMsgList)                {                                        Handler handler = msg.getHandler();                    try                    {                        sendMsg(msg.getBytes());                        sendMsgList.remove(msg);                        // 成功消息,通过hander回传                        if (handler != null)                        {                            Message message =  new Message();                            message.obj = msg.getBytes();                            message.what =1;                           handler.sendMessage(message);                        //    handler.sendEmptyMessage(1);                        }                                            } catch (Exception e)                    {                        e.printStackTrace();                        CLog.e(tag, e.toString());                        // 错误消息,通过hander回传                        if (handler != null)                        {                            Message message =  new Message();                            message.obj = msg.getBytes();                            message.what = 0;;                            handler.sendMessage(message);                                                }                    }                }            }                        synchronized (this)            {                try                {                    wait();                                    } catch (InterruptedException e)                {                    // TODO Auto-generated catch block                    e.printStackTrace();                }// 发送完消息后,线程进入等待状态            }        }            }}
复制代码

SocketInputThread

复制代码
package com.example.socketblockdemo;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.nio.ByteBuffer;import java.nio.channels.CancelledKeyException;import java.nio.channels.ClosedSelectorException;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;import java.nio.charset.CharacterCodingException;import java.nio.charset.Charset;import android.content.Intent;import android.text.TextUtils;/** * 客户端读消息线程 *  * @author way *  */public class SocketInputThread extends Thread{    private boolean isStart = true;        private static String tag = "socket";        // private MessageListener messageListener;// 消息监听接口对象        public SocketInputThread()    {    }        public void setStart(boolean isStart)    {        this.isStart = isStart;    }        @Override    public void run()    {        while (isStart)        {            // 手机能联网,读socket数据            if (NetManager.instance().isNetworkConnected())            {                                if (!TCPClient.instance().isConnect())                {                    CLog.e(tag, "TCPClient connet server is fail read thread sleep second" +Const.SOCKET_SLEEP_SECOND );                                        try                    {                        sleep(Const.SOCKET_SLEEP_SECOND * 1000);                    } catch (InterruptedException e)                    {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }                                readSocket();                                // 如果连接服务器失败,服务器连接失败,sleep固定的时间,能联网,就不需要sleep                                CLog.e("socket","TCPClient.instance().isConnect() " + TCPClient.instance().isConnect() );                                            }        }    }        public void readSocket()    {        Selector selector = TCPClient.instance().getSelector();        if (selector == null)        {            return;        }        try        {            // 如果没有数据过来,一直柱塞            while (selector.select() > 0)            {                for (SelectionKey sk : selector.selectedKeys())                {                    // 如果该SelectionKey对应的Channel中有可读的数据                    if (sk.isReadable())                    {                        // 使用NIO读取Channel中的数据                        SocketChannel sc = (SocketChannel) sk.channel();                        ByteBuffer buffer = ByteBuffer.allocate(1024);                        try                        {                            sc.read(buffer);                        } catch (IOException e)                        {                            // TODO Auto-generated catch block                            e.printStackTrace();                            // continue;                        }                        buffer.flip();                        String receivedString = "";                        // 打印收到的数据                        try                        {                            receivedString = Charset.forName("UTF-8")                                    .newDecoder().decode(buffer).toString();                                                        CLog.e(tag, receivedString);                                                        Intent i = new Intent(Const.BC);                                                        i.putExtra("response", receivedString);                                                        MainActivity.s_context.sendBroadcast(i );                                                    } catch (CharacterCodingException e)                        {                            // TODO Auto-generated catch block                            e.printStackTrace();                        }                        buffer.clear();                        buffer = null;                                                try                        {                            // 为下一次读取作准备                            sk.interestOps(SelectionKey.OP_READ);                            // 删除正在处理的SelectionKey                            selector.selectedKeys().remove(sk);                                                    } catch (CancelledKeyException e)                        {                            e.printStackTrace();                        }                                                                }                }            }            // selector.close();            // TCPClient.instance().repareRead();                    } catch (IOException e1)        {            // TODO Auto-generated catch block            e1.printStackTrace();        } catch (ClosedSelectorException e2)        {        }    }    }
复制代码

SocketHeartHread 心态类

 View Code

 

线程管理类

复制代码
package com.example.socketblockdemo;import android.os.Handler;import android.text.TextUtils;public class SocketThreadManager{        private static SocketThreadManager s_SocketManager = null;        private SocketInputThread mInputThread = null;        private SocketOutputThread mOutThread = null;        private SocketHeartThread mHeartThread = null;        // 获取单例    public static SocketThreadManager sharedInstance()    {        if (s_SocketManager == null)        {            s_SocketManager = new SocketThreadManager();            s_SocketManager.startThreads();        }        return s_SocketManager;    }        // 单例,不允许在外部构建对象    private SocketThreadManager()    {        mHeartThread = new SocketHeartThread();        mInputThread = new SocketInputThread();        mOutThread = new SocketOutputThread();    }        /**     * 启动线程     */        private void startThreads()    {        mHeartThread.start();        mInputThread.start();        mInputThread.setStart(true);        mOutThread.start();        mInputThread.setStart(true);        // mDnsthread.start();    }        /**     * stop线程     */    public void stopThreads()    {        mHeartThread.stopThread();        mInputThread.setStart(false);        mOutThread.setStart(false);    }        public static void releaseInstance()    {        if (s_SocketManager != null)        {            s_SocketManager.stopThreads();            s_SocketManager = null;        }    }        public void sendMsg(byte [] buffer, Handler handler)    {        MsgEntity entity = new MsgEntity(buffer, handler);        mOutThread.addMsgToSendList(entity);    }    }
复制代码

 

TCPClient ,采用NIO的方式构建

 View Code

 

如何使用

            // 发送消息,失败或者成功的handler            SocketThreadManager.sharedInstance().sendMsg(str.getBytes(), handler);

 

 

代码下载 http://files.cnblogs.com/likwo/SocketBlockDemo.zip

0 0
原创粉丝点击