亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

android socket聊天室功能實(shí)現(xiàn)

 更新時(shí)間:2017年03月30日 10:50:39   作者:許佳佳233  
這篇文章主要為大家詳細(xì)介紹了android socket聊天室功能實(shí)現(xiàn)方法,不單純是聊天室,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

前提概要

筆者很久之前其實(shí)就已經(jīng)學(xué)習(xí)過(guò)了socket,當(dāng)然也是用socket做過(guò)了聊天室,但是覺(jué)得此知識(shí)點(diǎn)比較一般,并無(wú)特別難的技術(shù)點(diǎn),于是也并未深究。
然而近期一個(gè)項(xiàng)目中對(duì)socket的使用卻讓筆者感覺(jué)socket強(qiáng)大無(wú)比,可以實(shí)現(xiàn)諸多功能。

個(gè)人Socket體驗(yàn)

項(xiàng)目主要有關(guān)智能家居,需要實(shí)現(xiàn)多臺(tái)手機(jī)同時(shí)對(duì)燈進(jìn)行操作(開(kāi)或者關(guān)),主要需要實(shí)現(xiàn)以下幾點(diǎn):

1、進(jìn)入界面時(shí)獲取所有燈的狀態(tài)。
2、一臺(tái)手機(jī)改變了燈的狀態(tài),其他的手機(jī)上可以有所顯示。
3、硬件上改變了燈的狀態(tài)(手動(dòng)開(kāi)關(guān)燈),所有手機(jī)上要有所顯示。

此功能如果使用HTTP讀取的方式實(shí)現(xiàn)就不太合適了。一方面客戶端與服務(wù)器讀取文件的同步性難以保證,即使保證了,也需要浪費(fèi)大量性能;另一方面,類似筆者的這種項(xiàng)目功能服務(wù)器和客戶端交互比較頻繁,對(duì)“即時(shí)性”要求也比較高,用HTTP不僅性能消耗太大,而且難以保證“即時(shí)性”。

但是使用Socket就很容易實(shí)現(xiàn)了,主要邏輯如下:

1、每次進(jìn)入界面與服務(wù)器建立Socket連接,并得到此時(shí)燈的狀態(tài)
2、每次需要對(duì)燈進(jìn)行操作的時(shí)候建立一個(gè)線程把燈的狀態(tài)傳遞給服務(wù)器,服務(wù)器接收到之后,把該狀態(tài)傳遞給每一個(gè)此時(shí)與服務(wù)器建立連接的客戶端。

此次體驗(yàn)也是讓筆者想起了學(xué)長(zhǎng)之前做的一道筆試題,題目大概如下:

將淘寶網(wǎng)頁(yè)和手機(jī)版同時(shí)打開(kāi)賬戶,手機(jī)停留在購(gòu)物車(chē)界面,此時(shí)網(wǎng)頁(yè)上將某一物品加入購(gòu)物車(chē),如何設(shè)計(jì)才能讓手機(jī)自動(dòng)刷新購(gòu)物車(chē)。

如果使用socket,相信是一個(gè)不錯(cuò)的思路。

好了,接下來(lái)進(jìn)入正題,展示socket聊天室demo。

效果(源碼在文章結(jié)尾)

主要思路

Android

1、進(jìn)入界面客戶端與服務(wù)器建立socket,同時(shí)此時(shí)開(kāi)啟一個(gè)線程一直接收服務(wù)器發(fā)送來(lái)的消息。
2、每次點(diǎn)擊button獲取EditText中的字符串,調(diào)用子線程把字符串發(fā)送給服務(wù)器。

服務(wù)器

1、創(chuàng)建一個(gè)ArrayList存儲(chǔ)Socket。
2、循環(huán)接收請(qǐng)求訪問(wèn)該端口的客戶端,接收到之后,把該socket存儲(chǔ)到ArrayList中,并且為每一個(gè)socket開(kāi)啟一個(gè)線程用于通信。
3、每個(gè)socket的線程的邏輯如下:循環(huán)接收客戶端發(fā)來(lái)的消息,接收到之后,利用之前的ArrayList,發(fā)送到每一個(gè)客戶端。如果某個(gè)客戶端返回空值或者無(wú)法發(fā)送過(guò)去,那么表示該客戶端已經(jīng)斷開(kāi),就從ArrayList中移除。

代碼

(借鑒《Android瘋狂講義》)

Android

不要忘記在AndroidManifest里面加上訪問(wèn)網(wǎng)絡(luò)的權(quán)限

MainActivity:

package com.example.double2.sockettesttwo;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

 private EditText etMain;
 private Button btnMain;
 private TextView tvMain;
 private ClientThread mClientThread;

 //在主線程中定義Handler傳入子線程用于更新TextView
 private Handler mHandler;

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

 etMain = (EditText) findViewById(R.id.et_main);
 btnMain = (Button) findViewById(R.id.btn_main);
 tvMain = (TextView) findViewById(R.id.tv_main);

 mHandler=new Handler() {
  @Override
  public void handleMessage(Message msg) {
  if (msg.what == 0) {
   tvMain.append("\n" + msg.obj.toString());
  }
  }
 };

 //點(diǎn)擊button時(shí),獲取EditText中string并且調(diào)用子線程的Handler發(fā)送到服務(wù)器
 btnMain.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
  try {
   Message msg = new Message();
   msg.what = 1;
   msg.obj = etMain.getText().toString();
   mClientThread.revHandler.sendMessage(msg);
   etMain.setText("");
  } catch (Exception e) {
   e.printStackTrace();
  }
  }
 });


 mClientThread = new ClientThread(mHandler);
 new Thread(mClientThread).start();


 }
}

ClientThread

package com.example.double2.sockettesttwo;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

/**
 * 項(xiàng)目名稱:SocketTestTwo
 * 創(chuàng)建人:Double2號(hào)
 * 創(chuàng)建時(shí)間:2016.11.20 9:16
 * 修改備注:
 */
public class ClientThread implements Runnable {
 private Socket mSocket;
 private BufferedReader mBufferedReader = null;
 private OutputStream mOutputStream = null;
 private Handler mHandler;

 public Handler revHandler;

 public ClientThread(Handler handler) {
 mHandler = handler;
 }

 @Override
 public void run() {
 try {
  mSocket = new Socket("10.3.20.159", 30003);
  Log.d("xjj","connect success");
  mBufferedReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
  mOutputStream = mSocket.getOutputStream();

  new Thread(){
  @Override
  public void run() {
   super.run();
   try {
   String content = null;
   while ((content = mBufferedReader.readLine()) != null) {
    Log.d("xjj",content);
    Message msg = new Message();
    msg.what = 0;
    msg.obj = content;
    mHandler.sendMessage(msg);
   }
   }catch (IOException e){
   e.printStackTrace();
   }
  }
  }.start();

  //由于子線程中沒(méi)有默認(rèn)初始化Looper,要在子線程中創(chuàng)建Handler,需要自己寫(xiě)
  Looper.prepare();
  revHandler = new Handler() {
  @Override
  public void handleMessage(Message msg) {
   if (msg.what == 1) {
   try {
    mOutputStream.write((msg.obj.toString() + "\r\n").getBytes("utf-8"));
   } catch (IOException e) {
    e.printStackTrace();
   }
   }
  }
  };
  Looper.loop();



 } catch (IOException e) {
  e.printStackTrace();
  Log.d("xjj","");
 }
 }
}

activity_main

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/activity_main"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:padding="@dimen/activity_vertical_margin"
 android:orientation="vertical"
 >

 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:orientation="horizontal">

 <EditText
  android:id="@+id/et_main"
  android:layout_width="0dp"
  android:layout_height="wrap_content"
  android:layout_weight="1"/>

 <Button
  android:id="@+id/btn_main"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="@string/send"/>
 </LinearLayout>

 <TextView
 android:id="@+id/tv_main"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 />
</LinearLayout>

服務(wù)器:

MySever

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class MySever {

 public static ArrayList<Socket> socketList = new ArrayList<Socket>();
 public static String content="";

 public static void main(String[] args) throws IOException {
 //建立ServerSocket
 ServerSocket ss = new ServerSocket(30003);

 //不斷接收此端口的socket,并存儲(chǔ)到socketList中
 //并且為每一個(gè)socket開(kāi)啟一個(gè)線程,用于接收信息
 while (true) {
  Socket s = ss.accept();
  System.out.println("connect success!");
  socketList.add(s);

  new Thread(new ServerThread(s)).start();
 }
 }

}

SeverThread

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.SocketException;
import java.util.Iterator;

public class ServerThread implements Runnable {

 private Socket mSocket = null;
 private BufferedReader mBufferedReader = null;

 // 構(gòu)造函數(shù)中接收socket并且初始化BufferedReader
 public ServerThread(Socket socket) 
  throws UnsupportedEncodingException, IOException {
 mSocket = socket;
 mBufferedReader = new BufferedReader(
  new InputStreamReader(mSocket.getInputStream(), "utf-8"));
 }

 @Override
 public void run() {
 // TODO Auto-generated method stub

 try {
  String content = null;

  //循環(huán)接收來(lái)自此客戶端的消息
  //如果接收不到了,表面已經(jīng)斷開(kāi),就將此客戶端從socketList中移除
  while ((content = mBufferedReader.readLine()) != null) {

  System.out.println(content);

  //向連接中的每個(gè)客戶端發(fā)送數(shù)據(jù)
  //如果異常,說(shuō)明斷開(kāi),就將該條目從socketList中移除
  for (Iterator<Socket> it = MySever.socketList.iterator(); 
   it.hasNext();) {
   Socket s = it.next();
   try {
   OutputStream os = s.getOutputStream();
   os.write((content + "\n").getBytes("utf-8"));
   } catch (SocketException e) {
   e.printStackTrace();
   it.remove();
   }
  }
  }
 } catch (IOException e) {
  e.printStackTrace();
  MySever.socketList.remove(mSocket);
 }
 }

}

源碼地址:android socket聊天室

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android Studio手動(dòng)打包的教程圖解

    Android Studio手動(dòng)打包的教程圖解

    項(xiàng)目寫(xiě)完了,現(xiàn)在需要把應(yīng)用上傳到市場(chǎng)上面,那么怎么把項(xiàng)目打包成apk呢?下面腳本之家小編給大家?guī)?lái)了Android Studio手動(dòng)打包的方法,一起看看吧
    2018-07-07
  • Jetpack Compose圖片組件使用實(shí)例詳細(xì)講解

    Jetpack Compose圖片組件使用實(shí)例詳細(xì)講解

    在Compose中,圖片組件主要有兩種,分別是顯示圖標(biāo)的Icon組件和顯示圖片的Image組件,當(dāng)我們顯示一系列的小圖標(biāo)的時(shí)候,我們可以使用Icon組件,當(dāng)顯示圖片時(shí),我們就用專用的Image組件
    2023-04-04
  • Android中的廣播和廣播接收器代碼實(shí)例

    Android中的廣播和廣播接收器代碼實(shí)例

    這篇文章主要介紹了Android中的廣播和廣播接收器代碼實(shí)例,本文講解了定義一個(gè)廣播接收器、發(fā)送廣播,定義好action標(biāo)志、用Intent發(fā)送、注冊(cè)只接收指定action的廣播接收器、取消該廣播接收器等操作代碼實(shí)例,需要的朋友可以參考下
    2015-05-05
  • Android通過(guò)原生方式獲取經(jīng)緯度與城市信息的方法

    Android通過(guò)原生方式獲取經(jīng)緯度與城市信息的方法

    這篇文章主要給大家介紹了關(guān)于Android通過(guò)原生方式獲取經(jīng)緯度與城市信息的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)各位Android開(kāi)發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Android列表對(duì)話框用法實(shí)例分析

    Android列表對(duì)話框用法實(shí)例分析

    這篇文章主要介紹了Android列表對(duì)話框用法,實(shí)例分析了Android實(shí)現(xiàn)列表對(duì)話框的布局、設(shè)置及功能等相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-09-09
  • Android屏蔽軟鍵盤(pán)并且顯示光標(biāo)的實(shí)例詳解

    Android屏蔽軟鍵盤(pán)并且顯示光標(biāo)的實(shí)例詳解

    這篇文章主要介紹了Android屏蔽軟鍵盤(pán)并且顯示光標(biāo)的實(shí)例詳解的相關(guān)資料,希望通過(guò)本文能幫助到大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下
    2017-10-10
  • Android實(shí)現(xiàn)拖動(dòng)效果的兩種方法

    Android實(shí)現(xiàn)拖動(dòng)效果的兩種方法

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)拖動(dòng)效果的兩種方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • Android 7.0行為變更 FileUriExposedException解決方法

    Android 7.0行為變更 FileUriExposedException解決方法

    這篇文章主要介紹了Android 7.0行為變更 FileUriExposedException解決方法的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • Android編程使用AlarmManager設(shè)置鬧鐘的方法

    Android編程使用AlarmManager設(shè)置鬧鐘的方法

    這篇文章主要介紹了Android編程使用AlarmManager設(shè)置鬧鐘的方法,結(jié)合具體實(shí)例分析了Android基于AlarmManager實(shí)現(xiàn)鬧鐘功能的設(shè)置、取消、顯示等相關(guān)操作技巧,需要的朋友可以參考下
    2017-03-03
  • Android之淘寶商品列表長(zhǎng)按遮罩效果的實(shí)現(xiàn)

    Android之淘寶商品列表長(zhǎng)按遮罩效果的實(shí)現(xiàn)

    這篇文章主要介紹了Android之淘寶商品列表長(zhǎng)按遮罩效果的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-05-05

最新評(píng)論