溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么在Android中利用Socket實(shí)現(xiàn)服務(wù)器之間通信

發(fā)布時間:2021-04-09 15:46:49 來源:億速云 閱讀:201 作者:Leah 欄目:移動開發(fā)

怎么在Android中利用Socket實(shí)現(xiàn)服務(wù)器之間通信?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

一、首先進(jìn)行Server的編寫:

public class SocketServer {
 private static Socket mSocket;

 public static void main(String[] argc) {
  try {
   //1.創(chuàng)建一個服務(wù)器端Socket,即ServerSocket,指定綁定的端口,并監(jiān)聽此端口
   ServerSocket serverSocket = new ServerSocket(12345);
   InetAddress address = InetAddress.getLocalHost();
   String ip = address.getHostAddress();

   //2.調(diào)用accept()等待客戶端連接
   System.out.println("~~~服務(wù)端已就緒,等待客戶端接入~,服務(wù)端ip地址: " + ip);
   mSocket = serverSocket.accept();

   //3.連接后獲取輸入流,讀取客戶端信息
   InputStream is = null;
   InputStreamReader isr = null;
   BufferedReader br = null;
   OutputStream os = null;
   is = mSocket.getInputStream();
   isr = new InputStreamReader(is, "UTF-8");
   br = new BufferedReader(isr);
   String info = null;
   while ((info = br.readLine()) != null) {
    System.out.println("客戶端發(fā)送過來的信息" + info);
    if (info.equals(BackService.HEART_BEAT_STRING)) {
     sendmsg("ok");

    } else {
     sendmsg("服務(wù)器發(fā)送過來的信息" + info);

    }
   }

   mSocket.shutdownInput();
   mSocket.close();

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

}


 //為連接上服務(wù)端的每個客戶端發(fā)送信息
 public static void sendmsg(String msg) {
  PrintWriter pout = null;
  try {
   pout = new PrintWriter(new BufferedWriter(
    new OutputStreamWriter(mSocket.getOutputStream(), "UTF-8")), true);
   pout.println(msg);
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}

二、對客戶端的編寫,主要用用AIDL進(jìn)行Server和Client

AIDL 的編寫主要為以下三部分:

1、創(chuàng)建 AIDL

1)、創(chuàng)建要操作的實(shí)體類,實(shí)現(xiàn) Parcelable 接口,以便序列化/反序列化
2)、新建 aidl 文件夾,在其中創(chuàng)建接口 aidl 文件以及實(shí)體類的映射 aidl 文件
3)、Make project ,生成 Binder 的 Java 文件

2、服務(wù)端

1)、創(chuàng)建 Service,在其中創(chuàng)建上面生成的 Binder 對象實(shí)例,實(shí)現(xiàn)接口定義的方法
2)、在 onBind() 中返回

3、客戶端

1)、實(shí)現(xiàn) ServiceConnection 接口,在其中拿到 AIDL 類
2)、bindService()
3)、調(diào)用 AIDL 類中定義好的操作請求

IBackService.aidl 文件

package com.example.dell.aidlservice;

// Declare any non-default types here with import statements

interface IBackService {
 /**
  * Demonstrates some basic types that you can use as parameters
  * and return values in AIDL.
  */

 boolean sendMessage(String message);
}

Service的編寫,命名為BackService

public class BackService extends Service {
 private static final String TAG = "danxx";
 public static final String HEART_BEAT_STRING = "HeartBeat";//心跳包內(nèi)容
 /**
  * 心跳頻率
  */
 private static final long HEART_BEAT_RATE = 3 * 1000;
 /**
  * 服務(wù)器ip地址
  */
 public static final String HOST = "172.16.50.115";
 /**
  * 服務(wù)器端口號
  */
 public static final int PORT = 12345;
 /**
  * 服務(wù)器消息回復(fù)廣播
  */
 public static final String MESSAGE_ACTION = "message_ACTION";
 /**
  * 服務(wù)器心跳回復(fù)廣播
  */
 public static final String HEART_BEAT_ACTION = "heart_beat_ACTION";
 /**
  * 讀線程
  */
 private ReadThread mReadThread;

 private LocalBroadcastManager mLocalBroadcastManager;
 /***/
 private WeakReference<Socket> mSocket;

 // For heart Beat
 private Handler mHandler = new Handler();
 /**
  * 心跳任務(wù),不斷重復(fù)調(diào)用自己
  */
 private Runnable heartBeatRunnable = new Runnable() {

  @Override
  public void run() {
   if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {
    boolean isSuccess = sendMsg(HEART_BEAT_STRING);//就發(fā)送一個\r\n過去 如果發(fā)送失敗,就重新初始化一個socket
    if (!isSuccess) {
     mHandler.removeCallbacks(heartBeatRunnable);
     mReadThread.release();
     releaseLastSocket(mSocket);
     new InitSocketThread().start();
    }
   }
   mHandler.postDelayed(this, HEART_BEAT_RATE);
  }
 };

 private long sendTime = 0L;
 /**
  * aidl通訊回調(diào)
  */
 private IBackService.Stub iBackService = new IBackService.Stub() {

  /**
   * 收到內(nèi)容發(fā)送消息
   * @param message 需要發(fā)送到服務(wù)器的消息
   * @return
   * @throws RemoteException
   */
  @Override
  public boolean sendMessage(String message) throws RemoteException {
   return sendMsg(message);
  }
 };

 @Override
 public IBinder onBind(Intent arg0) {
  return iBackService;
 }

 @Override
 public void onCreate() {
  super.onCreate();
  new InitSocketThread().start();
  mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
 }

 public boolean sendMsg(final String msg) {
  if (null == mSocket || null == mSocket.get()) {
   return false;
  }
  final Socket soc = mSocket.get();
  if (!soc.isClosed() && !soc.isOutputShutdown()) {
   new Thread(new Runnable() {
    @Override
    public void run() {
     try {
      OutputStream os = soc.getOutputStream();
      String message = msg + "\r\n";
      os.write(message.getBytes());
      os.flush();
     } catch (IOException e) {
      e.printStackTrace();
     }
    }
   }).start();
   sendTime = System.currentTimeMillis();//每次發(fā)送成數(shù)據(jù),就改一下最后成功發(fā)送的時間,節(jié)省心跳間隔時間
  } else {
   return false;
  }
  return true;
 }

 private void initSocket() {//初始化Socket
  try {
   //1.創(chuàng)建客戶端Socket,指定服務(wù)器地址和端口
   Socket so = new Socket(HOST, PORT);
   mSocket = new WeakReference<Socket>(so);
   mReadThread = new ReadThread(so);
   mReadThread.start();
   mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//初始化成功后,就準(zhǔn)備發(fā)送心跳包
  } catch (UnknownHostException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }

 /**
  * 心跳機(jī)制判斷出socket已經(jīng)斷開后,就銷毀連接方便重新創(chuàng)建連接
  *
  * @param mSocket
  */
 private void releaseLastSocket(WeakReference<Socket> mSocket) {
  try {
   if (null != mSocket) {
    Socket sk = mSocket.get();
    if (!sk.isClosed()) {
     sk.close();
    }
    sk = null;
    mSocket = null;
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
 }

 class InitSocketThread extends Thread {
  @Override
  public void run() {
   super.run();
   initSocket();
  }
 }

 // Thread to read content from Socket
 class ReadThread extends Thread {
  private WeakReference<Socket> mWeakSocket;
  private boolean isStart = true;

  public ReadThread(Socket socket) {
   mWeakSocket = new WeakReference<Socket>(socket);
  }

  public void release() {
   isStart = false;
   releaseLastSocket(mWeakSocket);
  }

  @Override
  public void run() {
   super.run();
   Socket socket = mWeakSocket.get();
   if (null != socket) {
    try {
     InputStream is = socket.getInputStream();
     byte[] buffer = new byte[1024 * 4];
     int length = 0;
     while (!socket.isClosed() && !socket.isInputShutdown() && isStart && ((length = is.read(buffer)) != -1)) {
      if (length > 0) {
       String message = new String(Arrays.copyOf(buffer, length)).trim();
       Log.e(TAG, message);
       //收到服務(wù)器過來的消息,就通過Broadcast發(fā)送出去
       if (message.equals("ok")) {//處理心跳回復(fù)
        Intent intent = new Intent(HEART_BEAT_ACTION);
        mLocalBroadcastManager.sendBroadcast(intent);

       } else {
        //其他消息回復(fù)
        Intent intent = new Intent(MESSAGE_ACTION);
        intent.putExtra("message", message);
        mLocalBroadcastManager.sendBroadcast(intent);
       }
      }
     }
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
  }
 }

 @Override
 public void onDestroy() {
  super.onDestroy();
  mHandler.removeCallbacks(heartBeatRunnable);
  mReadThread.release();
  releaseLastSocket(mSocket);
 }

}

MainActivity

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
 private TextView mResultText;
 private EditText mEditText;
 private Intent mServiceIntent;

 private IBackService iBackService;

 private ServiceConnection conn = new ServiceConnection() {

  @Override
  public void onServiceDisconnected(ComponentName name) {
   iBackService = null;

  }

  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
   iBackService = IBackService.Stub.asInterface(service);
  }
 };

 class MessageBackReciver extends BroadcastReceiver {
  private WeakReference<TextView> textView;

  public MessageBackReciver(TextView tv) {
   textView = new WeakReference<TextView>(tv);
  }

  @Override
  public void onReceive(Context context, Intent intent) {
   String action = intent.getAction();
   TextView tv = textView.get();
   if (action.equals(BackService.HEART_BEAT_ACTION)) {
    if (null != tv) {
     Log.i("danxx", "Get a heart heat");
     tv.setText("Get a heart heat");
    }
   } else {
    Log.i("danxx", "Get a heart heat");
    String message = intent.getStringExtra("message");
    tv.setText("服務(wù)器消息:" + message);
   }
  }
 }

 private MessageBackReciver mReciver;

 private IntentFilter mIntentFilter;

 private LocalBroadcastManager mLocalBroadcastManager;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);

  mResultText = (TextView) findViewById(R.id.resule_text);
  mEditText = (EditText) findViewById(R.id.content_edit);
  findViewById(R.id.send).setOnClickListener(this);
  findViewById(R.id.send1).setOnClickListener(this);
  mReciver = new MessageBackReciver(mResultText);

  mServiceIntent = new Intent(this, BackService.class);

  mIntentFilter = new IntentFilter();
  mIntentFilter.addAction(BackService.HEART_BEAT_ACTION);
  mIntentFilter.addAction(BackService.MESSAGE_ACTION);

 }

 @Override
 protected void onStart() {
  super.onStart();
  mLocalBroadcastManager.registerReceiver(mReciver, mIntentFilter);
  bindService(mServiceIntent, conn, BIND_AUTO_CREATE);
 }

 @Override
 protected void onStop() {
  super.onStop();
  unbindService(conn);
  mLocalBroadcastManager.unregisterReceiver(mReciver);
 }

 public void onClick(View view) {
  switch (view.getId()) {
   case R.id.send:
    String content = mEditText.getText().toString();
    try {
     boolean isSend = iBackService.sendMessage(content);//Send Content by socket
     Toast.makeText(this, isSend ? "success" : "fail", Toast.LENGTH_SHORT).show();
     mEditText.setText("");
    } catch (RemoteException e) {
     e.printStackTrace();
    }
    break;

   case R.id.send1:
    new Thread(new Runnable() {
     @Override
     public void run() {
      try {
       acceptServer();
      } catch (IOException e) {
       e.printStackTrace();
      }
     }
    }).start();
    break;

   default:
    break;
  }
 }


 private void acceptServer() throws IOException {
  //1.創(chuàng)建客戶端Socket,指定服務(wù)器地址和端口
  Socket socket = new Socket("172.16.50.115", 12345);
  //2.獲取輸出流,向服務(wù)器端發(fā)送信息
  OutputStream os = socket.getOutputStream();
  PrintWriter printWriter = new PrintWriter(os); //將輸出流包裝為打印流

  //獲取客戶端的IP地址
  InetAddress address = InetAddress.getLocalHost();
  String ip = address.getHostAddress();
  printWriter.write("客戶端:~" + ip + "~ 接入服務(wù)器?。?quot;);
  printWriter.flush();
  socket.shutdownInput();
  socket.close();
 }
}

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進(jìn)一步的了解或閱讀更多相關(guān)文章,請關(guān)注億速云行業(yè)資訊頻道,感謝您對億速云的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI