欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

Android使用多線程進(jìn)行網(wǎng)絡(luò)聊天室通信

TCP/IP通信協(xié)議是一種可靠的網(wǎng)絡(luò)協(xié)議,它在通信的兩端各建立一個(gè)Socket,從而在通信的兩端之間形成網(wǎng)絡(luò)虛擬鏈路。一旦建立了虛擬的網(wǎng)絡(luò)鏈路,兩端的程序就可以通過(guò)虛擬鏈路進(jìn)行通信了。Java對(duì)基于TCP協(xié)議的網(wǎng)絡(luò)通信提供了良好的封裝,Java使用Socket對(duì)象來(lái)代表兩端通信接口,并通過(guò)Socket產(chǎn)生IO流來(lái)進(jìn)行網(wǎng)絡(luò)通信。

創(chuàng)新互聯(lián)專注骨干網(wǎng)絡(luò)服務(wù)器租用10年,服務(wù)更有保障!服務(wù)器租用,綿陽(yáng)電信機(jī)房 成都服務(wù)器租用,成都服務(wù)器托管,骨干網(wǎng)絡(luò)帶寬,享受低延遲,高速訪問(wèn)。靈活、實(shí)現(xiàn)低成本的共享或公網(wǎng)數(shù)據(jù)中心高速帶寬的專屬高性能服務(wù)器。

下面的程序Demo是實(shí)現(xiàn)一個(gè)簡(jiǎn)單的C/S聊天室的應(yīng)用,每個(gè)客戶端該包含兩條線程:一條負(fù)責(zé)生成主界面,響應(yīng)用戶動(dòng)作,并將用戶輸入的數(shù)據(jù)寫入Socket對(duì)應(yīng)的輸出流中;另一條負(fù)責(zé)讀取Socket對(duì)應(yīng)的輸入流中的數(shù)據(jù)(從服務(wù)器發(fā)送過(guò)來(lái)的數(shù)據(jù)),并負(fù)責(zé)將這些數(shù)據(jù)在程序界面上顯示出來(lái)。
客戶端程序是一個(gè)Android應(yīng)用,因此需要?jiǎng)?chuàng)建一個(gè)Android項(xiàng)目,這個(gè)Android應(yīng)用的界面中包含兩個(gè)文本框:一個(gè)用于接收用戶的輸入;另一個(gè)用于顯示聊天信息。界面中還有一個(gè)按鈕,當(dāng)用戶單擊該按鈕時(shí),程序向服務(wù)器發(fā)送聊天信息。
layout/activity_main.xml界面布局代碼如下:

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

 <LinearLayout
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:orientation="horizontal">
  <!-- 定義一個(gè)文本框,它用于接收用戶的輸入 -->
  <EditText
   android:id="@+id/input"
   android:layout_width="280dp"
   android:layout_height="wrap_content" />

  <Button
   android:id="@+id/send"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:paddingLeft="8dp"
   android:text="發(fā)送" />
 </LinearLayout>
 <!-- 定義一個(gè)文本框,它用于顯示來(lái)自服務(wù)器的信息 -->
 <TextView
  android:id="@+id/show"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="#ffff"
  android:gravity="top"
  android:textColor="#f000"
  android:textSize="18sp" />
</LinearLayout>

客戶端的Activity負(fù)責(zé)生成程序界面,并為程序的按鈕單擊事件綁定事件監(jiān)聽器,當(dāng)用戶單擊按鈕時(shí)向服務(wù)器發(fā)送信息。
MainActivity.java邏輯代碼如下:

package com.fukaimei.multithreadclient;

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

public class MainActivity extends AppCompatActivity {

 // 定義界面上的兩個(gè)文本框
 EditText input;
 TextView show;
 // 定義界面上的一個(gè)按鈕
 Button send;
 Handler handler;
 // 定義與服務(wù)器通信的子線程
 ClientThread clientThread;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  input = (EditText) findViewById(R.id.input);
  send = (Button) findViewById(R.id.send);
  show = (TextView) findViewById(R.id.show);
  handler = new Handler() // ②
  {
   @Override
   public void handleMessage(Message msg) {
    // 如果消息來(lái)自于子線程
    if (msg.what == 0x123) {
     // 將讀取的內(nèi)容追加顯示在文本框中
     show.append("\n" + msg.obj.toString());
    }
   }
  };
  clientThread = new ClientThread(handler);
  // 客戶端啟動(dòng)ClientThread線程創(chuàng)建網(wǎng)絡(luò)連接、讀取來(lái)自服務(wù)器的數(shù)據(jù)
  new Thread(clientThread).start(); // ①
  send.setOnClickListener(new OnClickListener() {
   @Override
   public void onClick(View v) {
    try {
     // 當(dāng)用戶按下發(fā)送按鈕后,將用戶輸入的數(shù)據(jù)封裝成Message
     // 然后發(fā)送給子線程的Handler
     Message msg = new Message();
     msg.what = 0x234;
     msg.obj = input.getText().toString();
     clientThread.revHandler.sendMessage(msg);
     // 清空input文本框
     input.setText("");
    } catch (Exception e) {
     e.printStackTrace();
    }
   }
  });
 }
}

當(dāng)用戶單擊該程序界面中的“發(fā)送”按鈕后,程序?qū)?huì)把input輸入框中的內(nèi)容發(fā)送給clientThread的revHandler對(duì)象,clientThread負(fù)責(zé)將用戶輸入的內(nèi)容發(fā)送給服務(wù)器。

ClientThread子線程負(fù)責(zé)建立與遠(yuǎn)程服務(wù)器的連接,并負(fù)責(zé)與遠(yuǎn)程服務(wù)器通信,讀到數(shù)據(jù)之后便通過(guò)Handler對(duì)象發(fā)送一條消息;當(dāng)ClientThread子線程收到UI線程發(fā)送過(guò)來(lái)的消息后,還負(fù)責(zé)將用戶輸入的內(nèi)容發(fā)送給遠(yuǎn)程服務(wù)器。

ClientThread.java邏輯代碼如下:

package com.fukaimei.multithreadclient;

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;
import java.net.SocketTimeoutException;

public class ClientThread implements Runnable {

 private static final String TAG = "ClientThread";
 private Socket s;
 // 定義向UI線程發(fā)送消息的Handler對(duì)象
 private Handler handler;
 // 定義接收UI線程的消息的Handler對(duì)象
 public Handler revHandler;
 // 該線程所處理的Socket所對(duì)應(yīng)的輸入流
 BufferedReader br = null;
 OutputStream os = null;

 public ClientThread(Handler handler) {
  this.handler = handler;
 }

 public void run() {
  try {
   s = new Socket("172.xx.xx.xxx", 30000);
   br = new BufferedReader(new InputStreamReader(
     s.getInputStream()));
   os = s.getOutputStream();
   // 啟動(dòng)一條子線程來(lái)讀取服務(wù)器響應(yīng)的數(shù)據(jù)
   new Thread() {
    @Override
    public void run() {
     String content = null;
     // 不斷讀取Socket輸入流中的內(nèi)容
     try {
      while ((content = br.readLine()) != null) {
       // 每當(dāng)讀到來(lái)自服務(wù)器的數(shù)據(jù)之后,發(fā)送消息通知程序
       // 界面顯示該數(shù)據(jù)
       Message msg = new Message();
       msg.what = 0x123;
       msg.obj = content;
       handler.sendMessage(msg);
      }
     } catch (IOException e) {
      e.printStackTrace();
     }
    }
   }.start();
   // 為當(dāng)前線程初始化Looper
   Looper.prepare();
   // 創(chuàng)建revHandler對(duì)象
   revHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
     // 接收到UI線程中用戶輸入的數(shù)據(jù)
     if (msg.what == 0x234) {
      // 將用戶在文本框內(nèi)輸入的內(nèi)容寫入網(wǎng)絡(luò)
      try {
       os.write((msg.obj.toString() + "\r\n")
         .getBytes("utf-8"));
      } catch (Exception e) {
       e.printStackTrace();
      }
     }
    }
   };
   // 啟動(dòng)Looper
   Looper.loop();
  } catch (SocketTimeoutException e1) {
   Log.d(TAG, "網(wǎng)絡(luò)連接超時(shí)!");
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}

上面線程的功能也非常簡(jiǎn)單,它只是不斷地獲取Socket輸入流中的內(nèi)容,當(dāng)讀到Socket輸入流中的內(nèi)容后,便通過(guò)Handler對(duì)象發(fā)送一條消息,消息負(fù)責(zé)攜帶讀到的數(shù)據(jù)。除此之外,該子線程還負(fù)責(zé)讀取UI線程發(fā)送的消息,接收到消息之后,該子線程負(fù)責(zé)中攜帶的數(shù)據(jù)發(fā)送給遠(yuǎn)程服務(wù)器。

服務(wù)器端應(yīng)該包含多條線程,每個(gè)Socket對(duì)應(yīng)一條線程,該線程負(fù)責(zé)讀取Socket對(duì)應(yīng)輸入流,并將讀到的數(shù)據(jù)向每個(gè)Socket輸出流發(fā)送一遍,因此需要在服務(wù)器端使用List來(lái)保存所有的Socket。
下面是服務(wù)器端的代碼。程序?yàn)榉?wù)器提供了兩個(gè)類:一個(gè)是創(chuàng)建ServerSocket監(jiān)聽的主類;另一個(gè)是負(fù)責(zé)處理每個(gè)Socket通信的線程類。

/MultiThreadServer/src/MyServer.java邏輯代碼如下:

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

public class MyServer {

 // 定義保存所有Socket的ArrayList
 public static ArrayList<Socket> socketList = new ArrayList<Socket>();

 public static void main(String[] args) throws IOException {
  ServerSocket ss = new ServerSocket(30000);
  while (true) {
   // 此行代碼會(huì)阻塞,將一直等待別人的連接
   Socket s = ss.accept();
   socketList.add(s);
   // 每當(dāng)客戶端連接后啟動(dòng)一條ServerThread線程為該客戶端服務(wù)
   new Thread(new ServerThread(s)).start();
  }
 }
}

上面的程序是服務(wù)器端只負(fù)責(zé)接收客戶端Socket的連接請(qǐng)求,每當(dāng)客戶端Socket連接到該ServerSocket之后,程序?qū)?duì)應(yīng)Socket加入socketList集合中保存,并為該Socket啟動(dòng)一條線程,該程序負(fù)責(zé)處理該Socket所有的通信任務(wù)。服務(wù)器端線程類的代碼如下。

/MultiThreadServer/src/ServerThread.java邏輯代碼如下:

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

// 負(fù)責(zé)處理每條線程通信的線程類
public class ServerThread implements Runnable {
 // 定義當(dāng)前線程所處理的Socket
 Socket s = null;
 // 該線程所處理的Socket所對(duì)應(yīng)的輸入流
 BufferedReader br = null;
 public ServerThread(Socket s) throws IOException {
  this.s = s;
  // 初始化該Socket對(duì)應(yīng)的輸入流
  br = new BufferedReader(new InputStreamReader(s.getInputStream(), "utf-8"));
 }
 @Override
 public void run() {
  String content = null;
  // 采用循環(huán)不斷從Socket中讀取客戶端發(fā)送過(guò)來(lái)的數(shù)據(jù)
  while ((content = readFromClient()) != null) {
   // 遍歷socketList中的每個(gè)Socket
   // 將讀取的內(nèi)容向每個(gè)Socket發(fā)送一次
   for (Iterator<Socket> it = MyServer.socketList.iterator(); it.hasNext();) {
    Socket s = it.next();
    try {
     OutputStream os = s.getOutputStream();
     os.write((content + "\n").getBytes("utf-8"));
    } catch (Exception e) {
     e.printStackTrace();
     // 刪除該Socket
     it.remove();
     System.out.println(MyServer.socketList);
    }
   }
  }
 }
 // 定義讀取客戶端數(shù)據(jù)的方法
 private String readFromClient() {
  try {
   return br.readLine();
  } catch (IOException e) { // 如果捕獲到異常,表明該Socket對(duì)應(yīng)的客戶端已經(jīng)關(guān)閉
   e.printStackTrace();
   // 刪除該Socket
   MyServer.socketList.remove(s);
  }
  return null;
 }
}

上面的服務(wù)器端線程類不斷讀取客戶端數(shù)據(jù),程序使用readFromClient()方法來(lái)讀取客戶端數(shù)據(jù),如果在讀數(shù)據(jù)過(guò)程中捕獲到IOException異常,則表明該Socket對(duì)應(yīng)的客戶端Socket出現(xiàn)問(wèn)題,程序就將該Socket從socketList中刪除。
當(dāng)服務(wù)器線程讀到客戶端數(shù)據(jù)之后,程序遍歷socketList集合,并將該數(shù)據(jù)向socketList集合中的每個(gè)Socket發(fā)送一次——該服務(wù)器線程將把從Socket中讀到的數(shù)據(jù)向socketList中的每個(gè)Socket轉(zhuǎn)發(fā)一次。

先運(yùn)行上面程序的MyServer類,該類運(yùn)行后只是作為服務(wù)器,看不到任何輸出。接著可以運(yùn)行Android客戶端——相當(dāng)于啟動(dòng)聊天界面登錄該服務(wù)器,接下來(lái)在任何一個(gè)Android客戶端輸入一些內(nèi)容后單擊“發(fā)送”按鈕,將可以看到所有客戶端(包含自己)都會(huì)收到剛剛輸入的內(nèi)容,這樣就簡(jiǎn)單實(shí)現(xiàn)了一個(gè)C/S結(jié)構(gòu)的聊天室的功能。
注意:由于該程序需要訪問(wèn)互聯(lián)網(wǎng),因此還需要在清單文件AndroidManifest.xml文件中授權(quán)訪問(wèn)互聯(lián)網(wǎng)的權(quán)限:

<!-- 授權(quán)訪問(wèn)互聯(lián)網(wǎng)-->
 <uses-permission android:name="android.permission.INTERNET" />

Demo程序運(yùn)行效果界面截圖如下:

Android使用多線程進(jìn)行網(wǎng)絡(luò)聊天室通信

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

網(wǎng)站欄目:Android使用多線程進(jìn)行網(wǎng)絡(luò)聊天室通信
URL網(wǎng)址:http://aaarwkj.com/article18/jpoigp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化服務(wù)器托管、網(wǎng)站維護(hù)響應(yīng)式網(wǎng)站、建站公司云服務(wù)器

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營(yíng)
免费国产午夜福利在线| 免费在线黄色生活大片| 欧美日韩黄色的三级视频| 日韩毛片中文字幕在线观看| 日韩av在线不卡一区二区| 日本黄色一区二区三区四区| 岛国av有码高清在线观看| 日韩欧美中文字幕区| 亚洲成av人一区二区三区| 亚洲国产免费一区二区| 能在线播放的国产三级| 亚洲精品高清一区二区| 人妻大乳一区二区三区| 国产激情在线四五区观看| 欧美成人夫妻性生活视频| 欧美日韩亚洲人人夜夜澡| 成年人在线免费观看国产| 国产精品大片久久激情四射| 色婷婷久久五月中文字幕| 亚洲国产高清国产拍精品| 四虎最新永久在线网站| 97国产精品亚洲精品| 欧美日韩精品久久影院| 久久精品噜噜噜成人av农村| 国产91九色蝌蚪在线观看| 美女一区二区三区日本美女在线观看 | 尤物在线观看精品视频| 18岁以下禁看视频网站| 欧美精品一区二区久久不卡| 国产一区精品在线免费看| 国产在线播放精品视频| 日韩精品高清中文字幕| 熟妇一区二区在线播放| 精品国产一区二区三区不卡| 国产91美女黄色在线观看| 国产高清精品在线一区| 亚洲欧美国产另类综合| 国产成人91精品免费看片| 一区二区三区视频观看在线| 精品av一区二区在线| 福利成人午夜国产一区|