在Java中我們可以利用socket編程實現聊天室,在Android中也一樣,因為Android完全支持JDK本身的TCP、UDP網絡通信API。我們可以使用ServerSocket、Socket來建立基於TCP/IP協議的網絡通信;也可以使用DatagramSocket、Datagrampacket、MulticastSocket來建立基於UDP協議的網絡通信。下面實現一個簡單的聊天室,服務器端完全用Java代碼實現,跟Android無關,客戶端用Android應用來實現。
服務器不斷讀取來自客戶端的信息,並即時地將信息發送給每個連接到本服務器上的客戶端,每個客戶端可以向服務器發送消息,並不斷地接收來自服務器的消息,並將消息顯示在界面上。這樣就實現了客戶端與客戶端之間的即時聊天功能。代碼如下:
服務器端:
創建服務器的主類:
服務器的線程類:
客戶端主類(Activity):
客戶端線程類:
Activity的佈局XML:
權限:
服務器不斷讀取來自客戶端的信息,並即時地將信息發送給每個連接到本服務器上的客戶端,每個客戶端可以向服務器發送消息,並不斷地接收來自服務器的消息,並將消息顯示在界面上。這樣就實現了客戶端與客戶端之間的即時聊天功能。代碼如下:
服務器端:
創建服務器的主類:
- package com.home.server;
 - import java.io.IOException;
 - import java.net.ServerSocket;
 - import java.net.Socket;
 - import java.util.ArrayList;
 - public class MyServer {
 - // 定義保存所有Socket的集合
 - public static ArrayList<Socket> socketList = new ArrayList<Socket>();
 - public static void main(String[] args) throws IOException {
 - ServerSocket ss = new ServerSocket( 20000 );
 - System.out.println( "服務器創建成功!" );
 - System.out.println( "等待客戶端的連接。。。" );
 - while ( true ) {
 - // 此行代碼會阻塞,等待用戶的連接
 - Socket socket = ss.accept();
 - System.out.println( "有客戶端連接進來!" );
 - socketList.add(socket);
 - // 每當客戶端連接後啟動一條ServerThread線程為該客戶端服務
 - new Thread( new ServerThread(socket)).start();
 - }
 - }
 - }
 
- package com.home.server;
 - import java.io.BufferedReader;
 - import java.io.IOException;
 - import java.io.InputStreamReader;
 - import java.io.OutputStream;
 - import java.net.Socket;
 - public class ServerThread implements Runnable {
 - // 定義當前線程所處理的Socket
 - private Socket socket = null ;
 - // 該線程所處理的Socket所對應的輸入流
 - BufferedReader br = null ;
 - public ServerThread(Socket socket) throws IOException {
 - this .socket = socket;
 - // 初始化該Socket對應的輸入流
 - br = new BufferedReader( new InputStreamReader(socket.getInputStream(),
 - "utf-8" ));
 - }
 - @Override
 - public void run() {
 - try {
 - String content = null ;
 - // 採用循環不斷從Socket中讀取客戶端發送過來的數據
 - while ((content = readFromClient()) != null ) {
 - // 遍歷socketList中的每個Socket,將讀到的內容向每個Socket發送一次
 - for (Socket s : MyServer.socketList) {
 - OutputStream os = s.getOutputStream();
 - os.write((content + "\n" ).getBytes( "utf-8" ));
 - }
 - }
 - } catch (Exception e) {
 - e.printStackTrace();
 - }
 - }
 - /**
 - * 定義讀取客戶端數據的方法
 - *
 - * @return
 - */
 - private String readFromClient() {
 - try {
 - return br.readLine();
 - }
 - // 如果捕捉到異常,表明該Socket對應的客戶端已經關閉
 - catch (Exception e) {
 - // 刪除該Socket
 - MyServer.socketList.remove(socket);
 - e.printStackTrace();
 - }
 - return null ;
 - }
 - }
 
- package com.home.activity;
 - import java.io.OutputStream;
 - import java.net.Socket;
 - import android.app.Activity;
 - import android.os.Bundle;
 - import android.os.Handler;
 - import android.os.Message;
 - import android.view.View;
 - import android.view.View.OnClickListener;
 - import android.widget.Button;
 - import android.widget.EditText;
 - import com.home.R;
 - import com.home.util.ClientThread;
 - public class MultiThreadClient extends Activity {
 - private EditText input, show;
 - private Button sendBtn;
 - private OutputStream os;
 - private Handler handler;
 - @Override
 - protected void onCreate(Bundle savedInstanceState) {
 - super .onCreate(savedInstanceState);
 - setContentView(R.layout.activity_main);
 - input = (EditText) findViewById(R.id.main_et_input);
 - show = (EditText) findViewById(R.id.main_et_show);
 - sendBtn = (Button) findViewById(R.id.main_btn_send);
 - handler = new Handler() {
 - @Override
 - public void handleMessage(Message msg) {
 - // 如果消息來自子線程
 - if (msg.what == 0x234 ) {
 - // 將讀取的內容追加顯示在文本框中
 - show.append( "\n" + msg.obj.toString());
 - }
 - }
 - };
 - Socket socket;
 - try {
 - socket = new Socket( "192.168.0.101" , 20000 );
 - // 客戶端啟動ClientThread線程不斷讀取來自服務器的數據
 - new Thread( new ClientThread(socket, handler)).start();
 - os = socket.getOutputStream();
 - } catch (Exception e) {
 - e.printStackTrace();
 - }
 - sendBtn.setOnClickListener( new OnClickListener() {
 - @Override
 - public void onClick(View v) {
 - try {
 - // 將用戶在文本框內輸入的內容寫入網絡
 - os.write((input.getText().toString() + "\r\n" ).getBytes());
 - // 清空input文本框數據
 - input.setText( "" );
 - } catch (Exception e) {
 - e.printStackTrace();
 - }
 - }
 - });
 - }
 - }
 
- package com.home.util;
 - import java.io.BufferedReader;
 - import java.io.IOException;
 - import java.io.InputStreamReader;
 - import java.net.Socket;
 - import android.os.Handler;
 - import android.os.Message;
 - public class ClientThread implements Runnable {
 - private Handler handler;
 - // 該線程所處理的Socket所對應的輸入流
 - private BufferedReader br = null ;
 - public ClientThread(Socket socket, Handler handler) throws IOException {
 - this .handler = handler;
 - br = new BufferedReader( new InputStreamReader(socket.getInputStream()));
 - }
 - @Override
 - public void run() {
 - try {
 - String content = null ;
 - // 不斷讀取Socket輸入流的內容
 - while ((content = br.readLine()) != null ) {
 - // 每當讀到來自服務器的數據之後,發送消息通知程序界面顯示該數據
 - Message msg = new Message();
 - msg.what = 0x234 ;
 - msg.obj = content;
 - handler.sendMessage(msg);
 - }
 - } catch (Exception e) {
 - e.printStackTrace();
 - }
 - }
 - }
 
- < 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" >
 - < EditText
 - android:id = "@+id/main_et_input"
 - android:layout_width = "240dp"
 - android:layout_height = "wrap_content" />
 - < Button
 - android:id = "@+id/main_btn_send"
 - android:layout_width = "match_parent"
 - android:layout_height = "wrap_content"
 - android:paddingLeft = "10dp"
 - android:text = "發送" />
 - </ LinearLayout >
 - < EditText
 - android:id = "@+id/main_et_show"
 - android:layout_width = "match_parent"
 - android:layout_height = "match_parent"
 - android:cursorVisible = "false"
 - android:editable = "false"
 - android:gravity = "top" />
 - </ LinearLayout >
 
- < uses-permission android:name = "android.permission.INTERNET" />
 


沒有留言:
張貼留言