欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android中使用socket通信實(shí)現(xiàn)消息推送的方法詳解

 更新時間:2016年04月23日 10:27:24   作者:Jimstin  
這篇文章主要介紹了Android中使用socket通信實(shí)現(xiàn)消息推送的方法,文中舉了一個消息發(fā)送端和一個消息接收端以及服務(wù)器端的例子來說明原理并且展示了客戶端的實(shí)現(xiàn),需要的朋友可以參考下

原理
最近用socket寫了一個消息推送的demo,在這里和大家分享一下。

主要實(shí)現(xiàn)了:一臺手機(jī)向另外一臺手機(jī)發(fā)送消息,這兩臺手機(jī)可以隨時自由發(fā)送文本消息進(jìn)行通信,類似我們常用的QQ。

效果圖:

2016423101913983.jpg (574×1015)

2016423101940190.png (480×854)

2016423102054594.jpg (720×1280)

原理:手機(jī)通過socket發(fā)送消息到服務(wù)器,服務(wù)器每接收到一條消息之后,都會把這條消息放進(jìn)一個messageList里面,服務(wù)器會不停地檢測messageList是否含有消息,如果有的話就會根據(jù)messageList里面item的數(shù)據(jù),推送到相應(yīng)的另一端手機(jī)上面。

下面簡單畫了一個圖來說明這個原理:

演示:手機(jī)客戶端client1發(fā)送消息msg1到手機(jī)客戶端client2,client2收到消息后回復(fù)msg2給client1

2016423102200108.png (585×438)

1.手機(jī)客戶端client1發(fā)送一條“msg1”的文本消息到服務(wù)器;

2.服務(wù)器收到來自client1的“msg1”消息后,把它add進(jìn)messageList里面;

3.服務(wù)器檢測到messageList里面含有消息(開啟服務(wù)器時就新建里一個檢測messageList的線程,線程里面有一個死循環(huán),用于不停檢測messageList是否含有消息);

4.服務(wù)器讀取消息數(shù)據(jù),如讀取到來自client1發(fā)給client2的消息“msg1”,那么服務(wù)器就把“msg1”推送到client2上;

5.client2檢測到服務(wù)器推送的消息,做出相應(yīng)的操作(如:震動、鈴聲、顯示消息等);

6.client2接收到來自服務(wù)器推送的“msg1”消息后,client2也回復(fù)一條文本消息“msg2”給client1,此過程和client1發(fā)送消息給client2一樣。

7.最后,client2就可以顯示來自client1發(fā)送的消息“msg1”,而client1則可以顯示來自client2的回復(fù)消息“msg2”。

實(shí)現(xiàn)過程
根據(jù)消息推送的原理圖,我們的實(shí)現(xiàn)過程主要分為Server端和Client端,Server端采用Java的編程,而Client端則用Android編程。

所以在這里也分別創(chuàng)建了兩個工程SocketServer和SocketClient

2016423102229375.jpg (269×207)

我們先來看一下SocketMessage.java類:

public class SocketMessage { 
 
  public int to;//socketID,指發(fā)送給誰 
  public int from;//socketID,指誰發(fā)送過來的 
  public String msg;//消息內(nèi)容 
  public String time;//接收時間 
  public SocketThread thread;//socketThread下面有介紹 
} 

該類是一個消息類,用于表示消息是由誰發(fā)給誰的、消息內(nèi)容是什么、接收時間是多少,只有幾個屬性,比較簡單。

而MyServer.java類就相對比較多一些代碼:

package com.jimstin.server; 
 
import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.InputStreamReader; 
import java.io.OutputStreamWriter; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.text.SimpleDateFormat; 
import java.util.ArrayList; 
import java.util.Date; 
 
import org.json.JSONObject; 
 
 
import com.jimstin.msg.SocketMessage; 
 
public class MyServer { 
 
  private boolean isStartServer; 
  private ServerSocket mServer; 
  /** 
   * 消息隊列,用于保存SocketServer接收來自于客戶機(jī)(手機(jī)端)的消息 
   */ 
  private ArrayList<SocketMessage> mMsgList = new ArrayList<SocketMessage>(); 
  /** 
   * 線程隊列,用于接收消息。每個客戶機(jī)擁有一個線程,每個線程只接收發(fā)送給自己的消息 
   */ 
  private ArrayList<SocketThread> mThreadList = new ArrayList<SocketThread>(); 
   
  /** 
   * 開啟SocketServer 
   */ 
  private void startSocket() { 
    try { 
      isStartServer = true; 
      int prot = 2000;//端口可以自己設(shè)置,但要和Client端的端口保持一致 
      mServer = new ServerSocket(prot);//創(chuàng)建一個ServerSocket 
      System.out.println("啟動server,端口:"+prot); 
      Socket socket = null; 
      int socketID = 0;//Android(SocketClient)客戶機(jī)的唯一標(biāo)志,每個socketID表示一個Android客戶機(jī) 
      //開啟發(fā)送消息線程 
      startSendMessageThread(); 
      //用一個循環(huán)來檢測是否有新的客戶機(jī)加入 
      while(isStartServer) { 
        //accept()方法是一個阻塞的方法,調(diào)用該方法后, 
        //該線程會一直阻塞,直到有新的客戶機(jī)加入,代碼才會繼續(xù)往下走 
        socket = mServer.accept(); 
        //有新的客戶機(jī)加入后,則創(chuàng)建一個新的SocketThread線程對象 
        SocketThread thread = new SocketThread(socket, socketID++); 
        thread.start(); 
        //將該線程添加到線程隊列 
        mThreadList.add(thread); 
      } 
       
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
  } 
   
  /** 
   * 開啟推送消息線程,如果mMsgList中有SocketMessage,則把該消息推送到Android客戶機(jī) 
   */ 
  public void startSendMessageThread() { 
    new Thread(){ 
      @Override 
      public void run() { 
        super.run(); 
        try { 
          /*如果isStartServer=true,則說明SocketServer已啟動, 
          用一個循環(huán)來檢測消息隊列中是否有消息,如果有,則推送消息到相應(yīng)的客戶機(jī)*/ 
          while(isStartServer) { 
            //判斷消息隊列中的長度是否大于0,大于0則說明消息隊列不為空 
            if(mMsgList.size() > 0) { 
              //讀取消息隊列中的第一個消息 
              SocketMessage from = mMsgList.get(0); 
              for(SocketThread to : mThreadList) { 
                if(to.socketID == from.to) { 
                  BufferedWriter writer = to.writer; 
                  JSONObject json = new JSONObject(); 
                  json.put("from", from.from); 
                  json.put("msg", from.msg); 
                  json.put("time", from.time); 
                  //writer寫進(jìn)json中的字符串?dāng)?shù)據(jù),末尾記得加換行符:"\n",否則在客戶機(jī)端無法識別 
                  //因?yàn)锽ufferedReader.readLine()方法是根據(jù)換行符來讀取一行的 
                  writer.write(json.toString()+"\n"); 
                  //調(diào)用flush()方法,刷新流緩沖,把消息推送到手機(jī)端 
                  writer.flush(); 
                  System.out.println("推送消息成功:"+from.msg+">> to socketID:"+from.to); 
                  break; 
                } 
              } 
              //每推送一條消息之后,就要在消息隊列中移除該消息 
              mMsgList.remove(0); 
            } 
            Thread.sleep(200); 
          } 
        } catch (Exception e) { 
          e.printStackTrace(); 
        } 
      } 
    }.start(); 
  } 
   
  /** 
   * 定義一個SocketThread類,用于接收消息 
   * 
   */ 
  public class SocketThread extends Thread { 
     
    public int socketID; 
    public Socket socket;//Socket用于獲取輸入流、輸出流 
    public BufferedWriter writer;//BufferedWriter 用于推送消息 
    public BufferedReader reader;//BufferedReader 用于接收消息 
     
    public SocketThread(Socket socket, int count) { 
      socketID = count; 
      this.socket = socket; 
      System.out.println("新增一臺客戶機(jī),socketID:"+socketID); 
    } 
     
    @Override 
    public void run() { 
      super.run(); 
 
      try { 
        //初始化BufferedReader 
        reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8")); 
        //初始化BufferedWriter 
        writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "utf-8")); 
        //如果isStartServer=true,則說明SocketServer已經(jīng)啟動, 
        //現(xiàn)在需要用一個循環(huán)來不斷接收來自客戶機(jī)的消息,并作其他處理 
        while(isStartServer) { 
          //先判斷reader是否已經(jīng)準(zhǔn)備好 
          if(reader.ready()) { 
            /*讀取一行字符串,讀取的內(nèi)容來自于客戶機(jī) 
            reader.readLine()方法是一個阻塞方法, 
            從調(diào)用這個方法開始,該線程會一直處于阻塞狀態(tài), 
            直到接收到新的消息,代碼才會往下走*/ 
            String data = reader.readLine(); 
            //講data作為json對象的內(nèi)容,創(chuàng)建一個json對象 
            JSONObject json = new JSONObject(data); 
            //創(chuàng)建一個SocketMessage對象,用于接收json中的數(shù)據(jù) 
            SocketMessage msg = new SocketMessage(); 
            msg.to = json.getInt("to"); 
            msg.msg = json.getString("msg"); 
            msg.from = socketID; 
            msg.time = getTime(System.currentTimeMillis()); 
            //接收到一條消息后,將該消息添加到消息隊列mMsgList 
            mMsgList.add(msg); 
            System.out.println("收到一條消息:"+json.getString("msg")+" >>>> to socketID:"+json.getInt("to")); 
          } 
          //睡眠100ms,每100ms檢測一次是否有接收到消息 
          Thread.sleep(100); 
        } 
         
      } catch (Exception e) { 
        e.printStackTrace(); 
      }  
       
    } 
  } 
  /** 
   * 獲取指定格式的時間字符串,通過毫秒轉(zhuǎn)換日期 
   * @param millTime 
   */ 
  private String getTime(long millTime) { 
    Date d = new Date(millTime); 
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
    return sdf.format(d); 
  } 
  public static void main(String[] args) { 
    MyServer server = new MyServer(); 
    server.startSocket(); 
  } 
 
} 

2.SocketClient工程

2016423102315850.jpg (276×358)

該工程是一個Android的工程,只有一個MainActivity.java和activity_main.xml文件,

先看一下activity_main.xml布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  xmlns:tools="http://schemas.android.com/tools" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent" 
  tools:context=".MainActivity" 
  android:orientation="vertical" > 
   
  <LinearLayout  
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:orientation="horizontal"> 
    <EditText  
      android:id="@+id/ip_edt" 
      android:layout_width="0dp" 
      android:layout_height="wrap_content" 
      android:layout_weight="1" 
      android:hint="ip" 
      android:text="172.16.1.200"/> 
    <EditText  
      android:id="@+id/port_edt" 
      android:layout_width="0dp" 
      android:layout_height="wrap_content" 
      android:layout_weight="1" 
      android:hint="port" 
      android:text="2000"/> 
  </LinearLayout> 
  <Button  
    android:id="@+id/start_btn" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:text="start"/> 
  <EditText  
    android:id="@+id/socket_id_edt" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:hint="socketID"/> 
   
 
   
  <EditText  
    android:id="@+id/msg_edt" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:minLines="5" 
    android:hint="content" 
    android:gravity="top" 
    /> 
  <Button  
    android:id="@+id/send_btn" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:text="send"/> 
  <TextView  
    android:id="@+id/console_txt" 
    android:layout_width="match_parent" 
    android:layout_height="0dp" 
    android:layout_weight="1"/>   
  <Button  
    android:id="@+id/clear_btn" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:text="clear"/> 
</LinearLayout> 

效果圖:

2016423102346449.jpg (720×1280)

MainActivity.java類:

package com.jimstin.socketclient; 
 
import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.OutputStreamWriter; 
import java.net.Socket; 
import java.net.UnknownHostException; 
import java.text.SimpleDateFormat; 
import java.util.Date; 
 
import org.json.JSONObject; 
 
import com.tencent.stat.MtaSDkException; 
import com.tencent.stat.StatConfig; 
import com.tencent.stat.StatService; 
 
import android.R.integer; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.util.Log; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.EditText; 
import android.widget.TextView; 
import android.widget.Toast; 
import android.app.Activity; 
 
public class MainActivity extends Activity implements OnClickListener { 
 
  private EditText mIPEdt, mPortEdt, mSocketIDEdt, mMessageEdt; 
  private static TextView mConsoleTxt; 
   
  private static StringBuffer mConsoleStr = new StringBuffer(); 
  private Socket mSocket; 
  private boolean isStartRecieveMsg; 
   
  private SocketHandler mHandler; 
  protected BufferedReader mReader;//BufferedWriter 用于推送消息 
  protected BufferedWriter mWriter;//BufferedReader 用于接收消息 
   
  @Override 
  protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    initView(); 
  } 
 
  private void initView() { 
    mIPEdt = (EditText) findViewById(R.id.ip_edt); 
    mPortEdt = (EditText) findViewById(R.id.port_edt); 
    mSocketIDEdt = (EditText) findViewById(R.id.socket_id_edt); 
    mMessageEdt = (EditText) findViewById(R.id.msg_edt); 
    mConsoleTxt = (TextView) findViewById(R.id.console_txt); 
    findViewById(R.id.start_btn).setOnClickListener(this); 
    findViewById(R.id.send_btn).setOnClickListener(this); 
    findViewById(R.id.clear_btn).setOnClickListener(this); 
    mHandler = new SocketHandler(); 
  } 
 
  /** 
   * 初始化socket 
   */ 
  private void initSocket() { 
    //新建一個線程,用于初始化socket和檢測是否有接收到新的消息 
    Thread thread = new Thread(new Runnable() { 
       
      @Override 
      public void run() { 
        String ip = mIPEdt.getText().toString();//IP 
        int port = Integer.parseInt(mPortEdt.getText().toString());//Socket 
         
        try { 
          isStartRecieveMsg = true; 
          mSocket = new Socket(ip, port); 
          mReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream(), "utf-8")); 
          mWriter = new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream(), "utf-8")); 
          while(isStartRecieveMsg) { 
            if(mReader.ready()) { 
              /*讀取一行字符串,讀取的內(nèi)容來自于客戶機(jī) 
              reader.readLine()方法是一個阻塞方法, 
              從調(diào)用這個方法開始,該線程會一直處于阻塞狀態(tài), 
              直到接收到新的消息,代碼才會往下走*/ 
              String data = mReader.readLine(); 
              //handler發(fā)送消息,在handleMessage()方法中接收 
              mHandler.obtainMessage(0, data).sendToTarget(); 
            } 
            Thread.sleep(200); 
          } 
          mWriter.close(); 
          mReader.close(); 
          mSocket.close(); 
        } catch (Exception e) { 
          e.printStackTrace(); 
        }  
      } 
    }); 
    thread.start(); 
  } 
   
  @Override 
  public void onClick(View v) { 
    switch (v.getId()) { 
    case R.id.send_btn: 
      send(); 
      break; 
    case R.id.clear_btn: 
      mConsoleStr.delete(0, mConsoleStr.length()); 
      mConsoleTxt.setText(mConsoleStr.toString()); 
      break; 
    case R.id.start_btn: 
      if(!isStartRecieveMsg) { 
        initSocket(); 
      } 
      break; 
    default: 
      break; 
    } 
  } 
 
  /** 
   * 發(fā)送 
   */ 
  private void send() { 
    new AsyncTask<String, Integer, String>() { 
 
      @Override 
      protected String doInBackground(String... params) { 
        sendMsg(); 
        return null; 
      } 
    }.execute(); 
  } 
  /** 
   * 發(fā)送消息 
   */ 
  protected void sendMsg() { 
    try { 
      String socketID = mSocketIDEdt.getText().toString().trim(); 
      String msg = mMessageEdt.getText().toString().trim(); 
      JSONObject json = new JSONObject(); 
      json.put("to", socketID); 
      json.put("msg", msg); 
      mWriter.write(json.toString()+"\n"); 
      mWriter.flush(); 
      mConsoleStr.append("我:" +msg+"  "+getTime(System.currentTimeMillis())+"\n"); 
      mConsoleTxt.setText(mConsoleStr); 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
  } 
 
  static class SocketHandler extends Handler { 
     
    @Override 
    public void handleMessage(Message msg) { 
      // TODO Auto-generated method stub 
      super.handleMessage(msg); 
      switch (msg.what) { 
      case 0: 
        try { 
          //將handler中發(fā)送過來的消息創(chuàng)建json對象 
          JSONObject json = new JSONObject((String)msg.obj); 
          mConsoleStr.append(json.getString("from")+":" +json.getString("msg")+"  "+getTime(System.currentTimeMillis())+"\n"); 
          //將json數(shù)據(jù)顯示在TextView中 
          mConsoleTxt.setText(mConsoleStr); 
        } catch (Exception e) { 
          e.printStackTrace(); 
        } 
         
        break; 
 
      default: 
        break; 
      } 
    } 
  } 
   
  @Override 
  public void onBackPressed() { 
    super.onBackPressed(); 
    isStartRecieveMsg = false; 
  } 
   
  private static String getTime(long millTime) { 
    Date d = new Date(millTime); 
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
    return sdf.format(d); 
  } 
   
} 

以上代碼的注釋都比較詳細(xì),就不再多說了。

相關(guān)文章

最新評論