Android 通过Socket 和服务器通讯

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

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

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

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

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

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

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

(5)构建 TCPClient 发送socket消息

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

 

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 心跳类

package com.example.socketblockdemo;

import java.io.IOException;

import android.text.TextUtils;

class SocketHeartThread extends Thread
{
    boolean isStop = false;
    boolean mIsConnectSocketSuccess = false;
    static SocketHeartThread s_instance;

    private TCPClient mTcpClient = null;

    static final String tag = "SocketHeartThread";

    public static synchronized SocketHeartThread instance()
    {
        if (s_instance == null)
        {
            s_instance = new SocketHeartThread();
        }
        return s_instance;
    }

    public SocketHeartThread()
    {
       TCPClient.instance();
                // 连接服务器
    //    mIsConnectSocketSuccess = connect();

    }

    public void stopThread()
    {
        isStop = true;
    }

    /**
     * 连接socket到服务器, 并发送初始化的Socket信息
     *
     * @return
     */

    private boolean reConnect()
    {
        return TCPClient.instance().reConnect();
    }

    public void run()
    {
        isStop = false;
        while (!isStop)
        {
                // 发送一个心跳包看服务器是否正常
                boolean canConnectToServer = TCPClient.instance().canConnectToServer();

                if(canConnectToServer == false){
                    reConnect();
                }
                try
                {
                    Thread.sleep(Const.SOCKET_HEART_SECOND * 1000);

                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
    }
}

线程管理类

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的方式构建

package com.example.socketblockdemo;

import java.io.IOException;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

/**
 * NIO TCP 客户端
 *
 */
public class TCPClient
{
    // 信道选择器
    private Selector selector;

    // 与服务器通信的信道
    SocketChannel socketChannel;

    // 要连接的服务器Ip地址
    private String hostIp;

    // 要连接的远程服务器在监听的端口
    private int hostListenningPort;

    private static TCPClient s_Tcp = null;

    public boolean isInitialized = false;

    public static synchronized TCPClient instance()
    {
        if (s_Tcp == null)
        {

            s_Tcp = new TCPClient(Const.SOCKET_SERVER,
                    Const.SOCKET_PORT);
        }
        return s_Tcp;
    }

    /**
     * 构造函数
     *
     * @param HostIp
     * @param HostListenningPort
     * @throws IOException
     */
    public TCPClient(String HostIp, int HostListenningPort)
    {
        this.hostIp = HostIp;
        this.hostListenningPort = HostListenningPort;

        try
        {
            initialize();
            this.isInitialized = true;
        } catch (IOException e)
        {
            this.isInitialized = false;
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e)
        {
            this.isInitialized = false;
            e.printStackTrace();
        }
    }

    /**
     * 初始化
     *
     * @throws IOException
     */
    public void initialize() throws IOException
    {
        boolean done = false;

        try
        {
            // 打开监听信道并设置为非阻塞模式
            socketChannel = SocketChannel.open(new InetSocketAddress(hostIp,
                    hostListenningPort));
            if (socketChannel != null)
            {
                socketChannel.socket().setTcpNoDelay(false);
                socketChannel.socket().setKeepAlive(true);
                // 设置 读socket的timeout时间
                socketChannel.socket().setSoTimeout(
                        Const.SOCKET_READ_TIMOUT);
                socketChannel.configureBlocking(false);

                // 打开并注册选择器到信道
                selector = Selector.open();
                if (selector != null)
                {
                    socketChannel.register(selector, SelectionKey.OP_READ);
                    done = true;
                }
            }
        } finally
        {
            if (!done && selector != null)
            {
                selector.close();
            }
            if (!done)
            {
                socketChannel.close();
            }
        }
    }

    static void blockUntil(SelectionKey key, long timeout) throws IOException
    {

        int nkeys = 0;
        if (timeout > 0)
        {
            nkeys = key.selector().select(timeout);

        } else if (timeout == 0)
        {
            nkeys = key.selector().selectNow();
        }

        if (nkeys == 0)
        {
            throw new SocketTimeoutException();
        }
    }

    /**
     * 发送字符串到服务器
     *
     * @param message
     * @throws IOException
     */
    public void sendMsg(String message) throws IOException
    {
        ByteBuffer writeBuffer = ByteBuffer.wrap(message.getBytes("utf-8"));

        if (socketChannel == null)
        {
            throw new IOException();
        }
        socketChannel.write(writeBuffer);
    }

    /**
     * 发送数据
     *
     * @param bytes
     * @throws IOException
     */
    public void sendMsg(byte[] bytes) throws IOException
    {
        ByteBuffer writeBuffer = ByteBuffer.wrap(bytes);

        if (socketChannel == null)
        {
            throw new IOException();
        }
        socketChannel.write(writeBuffer);
    }

    /**
     *
     * @return
     */
    public synchronized Selector getSelector()
    {
        return this.selector;
    }

    /**
     * Socket连接是否是正常的
     *
     * @return
     */
    public boolean isConnect()
    {
        boolean isConnect = false;
        if (this.isInitialized)
        {
            isConnect =  this.socketChannel.isConnected();
        }
        return isConnect;
    }

    /**
     * 关闭socket 重新连接
     *
     * @return
     */
    public boolean reConnect()
    {
        closeTCPSocket();

        try
        {
            initialize();
            isInitialized = true;
        } catch (IOException e)
        {
            isInitialized = false;
            e.printStackTrace();
        }
        catch (Exception e)
        {
            isInitialized = false;
            e.printStackTrace();
        }
        return isInitialized;
    }

    /**
     * 服务器是否关闭,通过发送一个socket信息
     *
     * @return
     */
    public boolean canConnectToServer()
    {
        try
        {
            if (socketChannel != null)
            {
                socketChannel.socket().sendUrgentData(0xff);
            }
        } catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        }
        catch (Exception e){
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 关闭socket
     */
    public void closeTCPSocket()
    {
        try
        {
            if (socketChannel != null)
            {
                socketChannel.close();
            }

        } catch (IOException e)
        {

        }
        try
        {
            if (selector != null)
            {
                selector.close();
            }
        } catch (IOException e)
        {
        }
    }

    /**
     * 每次读完数据后,需要重新注册selector,读取数据
     */
    public synchronized void repareRead()
    {
        if (socketChannel != null)
        {
            try
            {
                selector = Selector.open();
                socketChannel.register(selector, SelectionKey.OP_READ);
            } catch (ClosedChannelException e)
            {
                e.printStackTrace();

            } catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
}

如何使用

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

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

时间: 2024-11-03 23:07:47

Android 通过Socket 和服务器通讯的相关文章

模拟器 pc 通讯-android模拟器与pc服务器通讯

问题描述 android模拟器与pc服务器通讯 我现在做的可以实现模拟器和pc通讯,但是pc只能被动的接受信息然后在返回信息.那我要如何做才可以实现pc可以主动的发送消息给模拟器呢? 解决方案 通过sockect可以实现.服务端在PC端,客户端在Android模拟器.可以参考一下这个:http://blog.csdn.net/x605940745/article/details/17001641 解决方案二: 使用基于长连接的Socket可以实现,通信是双向的

通信-android 客户端socket连接服务器,socket何时close

问题描述 android 客户端socket连接服务器,socket何时close 假设socket连接好了,现在客户端向服务器发送完了数据,这个时候需要关闭socket吗?如果关闭后,某个时候又需要发送其他数据,再建立连接? 还是说建立通信协议,一次socket连接后一直保持通信状态,根据通信协议对不同的数据进行不同的处理,然后等客户端程序退出时再关闭socket. 解决方案 Android客户端通过Socket连接服务器Android客户端与java服务器端的Socket连接Socket服务

Android客户端与PC服务器如何实现Socket通信

本文介绍Android终端持续扫描AP信息并发送给服务器端的实现.首先基于TCP协议在Android终端和PC两端之间形成网络虚拟链路.使用ServerSocket创建TCP服务器端,然后在Android客户端使用Socket的构造器来连接服务器.其中Android终端通过WIFI连接和PC处于同一局域网. 1. PC服务器启用ServerSocket 两个通信实体在建立虚拟链路之前,需要有一方先准备好,主动接受来自其他通信实体的连接请求. 使用ServerSocket对象监听来自客户端的Soc

Android编程之客户端通过socket与服务器通信的方法

  Android编程之客户端通过socket与服务器通信的方法        本文实例讲述了Android编程之客户端通过socket与服务器通信的方法.分享给大家供大家参考,具体如下: 下面是一个demo,Android客户端通过socket与服务器通信. 由于Android里面可以完全使用java.io.*包和java.net.*包,那么,实际上,逻辑部分与J2SE没有区别.只是UI代码不一样. Android客户端通过socket与服务器通信分为下面5步: (1)通过IP地址和端口实例化

通信-pc机与android手机socket通讯的问题

问题描述 pc机与android手机socket通讯的问题 本人最近想做一个上微机在pc机上控制下位机(单片机)!同时这个上位机具有socket通信的功能能通过安卓手机远程控制上位机向单片机发送指令,现在pc机上的上位机做好了,然后使用winsocket服务端程序做好了!手机端安卓socket客户端!现在问题就是这两个socket之间好像不能通信啊!在电脑上使用java写的服务端可以和安卓手机通信! 我想问一下在电脑上用C语言和win api写的服务端有么有办法和安卓客户端的socket通信!有

Android的Socket通讯编程实例代码

android客户端通过socket与服务器进行通信可以分为以下几步: 应用程序与服务器通信可以采用两种模式:TCP可靠通信 和UDP不可靠通信. (1)通过IP地址和端口实例化Socket,请求连接服务器:  代码如下 复制代码      socket = new Socket(HOST, PORT);   //host:为服务器的IP地址  port:为服务器的端口号 (2)获取Socket流以进行读写,并把流包装进BufferWriter或者PrintWriter:  代码如下 复制代码

python服务器与android客户端socket通信实例_python

本文实例讲述了python服务器与android客户端socket通信的方法.分享给大家供大家参考.具体实现方法如下: 首先,服务器端使用python完成,下面为python代码: 复制代码 代码如下: #server.py  import socket  def getipaddrs(hostname):#只是为了显示IP,仅仅测试一下      result = socket.getaddrinfo(hostname, None, 0, socket.SOCK_STREAM)      re

Android编程之客户端通过socket与服务器通信的方法_Android

本文实例讲述了Android编程之客户端通过socket与服务器通信的方法.分享给大家供大家参考,具体如下: 下面是一个demo,Android客户端通过socket与服务器通信. 由于Android里面可以完全使用java.io.*包和java.net.*包,那么,实际上,逻辑部分与J2SE没有区别.只是UI代码不一样. Android客户端通过socket与服务器通信分为下面5步: (1)通过IP地址和端口实例化Socket,请求连接服务器: 复制代码 代码如下: socket = new

小弟目前要做一个SOCKET编程客户端通讯软件,与多个服务器进行通讯

问题描述 这个项目主要是上位机与下位机通讯方面的东西,因为之前从来没有写过这方面的软件,所以对这个是一无所知.这个软件我想实现的功能就是编写一个客户端上位机软件与多台服务器通讯,当然这些服务器都是一些网卡设备说具体一点就是一些带网卡的单片机或者ARM,在此之前我试了很多次方法(比如说异步多线程什么的)都没有成功但是几天前用了异步方法只是连接成功了但是异步接受还是不行,我知道解决这个方面的问题就是你连接多少个服务器IP就必须必须写多少个接收数据的方法,但是这个系统没有限制呀<有可能是100个设备,