国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

詳解Android 通過Socket 和服務(wù)器通訊(附demo)

2019-12-12 04:11:18
字體:
供稿:網(wǎng)友

Android 通過Socket 和服務(wù)器通訊,是一種比較常用的通訊方式,時(shí)間比較緊,說下大致的思路,希望能幫到使用socket 進(jìn)行通信的人

(1)開啟一個(gè)線程發(fā)送消息    SocketOutputThread

消息是放在隊(duì)列里的,當(dāng)有消息后,進(jìn)入隊(duì)列,線程喚醒,發(fā)送消息,并反饋發(fā)送是否成功的回調(diào)

(2)開啟一個(gè)線程接受服務(wù)器消息 SocketInputThread

為了防止一直收數(shù)據(jù),浪費(fèi)電池的電,采用NIO的方式讀socket的數(shù)據(jù),這個(gè)是本文的關(guān)鍵

(3)開啟一個(gè)線程,做心跳,防止socket連接終斷 , SocketHeartThread

 (4)構(gòu)建 SocketThreadManager對(duì)以上三個(gè)thread進(jìn)行管理

(5)構(gòu)建 TCPClient 發(fā)送socket消息

在NIO的方式實(shí)現(xiàn)TCP,特別是在接收服務(wù)器的數(shù)據(jù),不用寫個(gè)線程定時(shí)去讀了。

DEMO 截圖 

主要代碼如下,詳細(xì)代碼在附件里。

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發(fā)送消息 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發(fā)送消息 public void addMsgToSendList(MsgEntity msg)  {  synchronized (this)  {   this.sendMsgList.add(msg);   notify();  } }  @Override public void run() {  while (isStart)  {   // 鎖發(fā)送list   synchronized (sendMsgList)   {    // 發(fā)送消息    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());      // 錯(cuò)誤消息,通過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();    }// 發(fā)送完消息后,線程進(jìn)入等待狀態(tài)   }  }   }}

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;// 消息監(jiān)聽接口對(duì)象  public SocketInputThread() { }  public void setStart(boolean isStart) {  this.isStart = isStart; }  @Override public void run() {  while (isStart)  {   // 手機(jī)能聯(lián)網(wǎng),讀socket數(shù)據(jù)   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();        // 如果連接服務(wù)器失敗,服務(wù)器連接失敗,sleep固定的時(shí)間,能聯(lián)網(wǎng),就不需要sleep        CLog.e("socket","TCPClient.instance().isConnect() " + TCPClient.instance().isConnect() );           }  } }  public void readSocket() {  Selector selector = TCPClient.instance().getSelector();  if (selector == null)  {   return;  }  try  {   // 如果沒有數(shù)據(jù)過來,一直柱塞   while (selector.select() > 0)   {    for (SelectionKey sk : selector.selectedKeys())    {     // 如果該SelectionKey對(duì)應(yīng)的Channel中有可讀的數(shù)據(jù)     if (sk.isReadable())     {      // 使用NIO讀取Channel中的數(shù)據(jù)      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 = "";      // 打印收到的數(shù)據(jù)      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      {       // 為下一次讀取作準(zhǔn)備       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 心態(tài)類

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();    // 連接服務(wù)器 // mIsConnectSocketSuccess = connect(); } public void stopThread() {  isStop = true; }  /**  * 連接socket到服務(wù)器, 并發(fā)送初始化的Socket信息  *   * @return  */   private boolean reConnect() {  return TCPClient.instance().reConnect(); }  public void run() {  isStop = false;  while (!isStop)  {    // 發(fā)送一個(gè)心跳包看服務(wù)器是否正常    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; }  // 單例,不允許在外部構(gòu)建對(duì)象 private SocketThreadManager() {  mHeartThread = new SocketHeartThread();  mInputThread = new SocketInputThread();  mOutThread = new SocketOutputThread(); }  /**  * 啟動(dòng)線程  */  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的方式構(gòu)建 

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;  // 與服務(wù)器通信的信道 SocketChannel socketChannel;  // 要連接的服務(wù)器Ip地址 private String hostIp;  // 要連接的遠(yuǎn)程服務(wù)器在監(jiān)聽的端口 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; }  /**  * 構(gòu)造函數(shù)  *   * @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  {   // 打開監(jiān)聽信道并設(shè)置為非阻塞模式   socketChannel = SocketChannel.open(new InetSocketAddress(hostIp,     hostListenningPort));   if (socketChannel != null)   {    socketChannel.socket().setTcpNoDelay(false);    socketChannel.socket().setKeepAlive(true);    // 設(shè)置 讀socket的timeout時(shí)間    socketChannel.socket().setSoTimeout(      Const.SOCKET_READ_TIMOUT);    socketChannel.configureBlocking(false);        // 打開并注冊(cè)選擇器到信道    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();  } }  /**  * 發(fā)送字符串到服務(wù)器  *   * @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); }  /**  * 發(fā)送數(shù)據(jù)  *   * @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; }  /**  * 關(guān)閉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; }  /**  * 服務(wù)器是否關(guān)閉,通過發(fā)送一個(gè)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; }  /**  * 關(guān)閉socket  */ public void closeTCPSocket() {  try  {   if (socketChannel != null)   {    socketChannel.close();   }     } catch (IOException e)  {     }  try  {   if (selector != null)   {    selector.close();   }  } catch (IOException e)  {  } }  /**  * 每次讀完數(shù)據(jù)后,需要重新注冊(cè)selector,讀取數(shù)據(jù)  */ 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();   }  } }}

如何使用

// 發(fā)送消息,失敗或者成功的handlerSocketThreadManager.sharedInstance().sendMsg(str.getBytes(), handler);

代碼下載:demo

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 屯留县| 读书| 理塘县| 读书| 灵宝市| 冕宁县| 穆棱市| 从江县| 伊宁市| 永登县| 杂多县| 公主岭市| 黄梅县| 商丘市| 霍邱县| 镇安县| 江川县| 江孜县| 营山县| 灵山县| 郎溪县| 万荣县| 青铜峡市| 万全县| 清原| 色达县| 时尚| 长丰县| 聂荣县| 乌审旗| 衢州市| 汝城县| 措美县| 芒康县| 互助| 建瓯市| 郑州市| 苍梧县| 新兴县| 蓬安县| 固阳县|