溫馨提示×

溫馨提示×

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

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

Android實現C/S聊天室

發(fā)布時間:2020-08-22 08:03:25 來源:腳本之家 閱讀:122 作者:Knick_Zhang 欄目:移動開發(fā)

Java中能接受其他通信實體鏈接請求的類是ServerSocket,ServerSocket對象用于監(jiān)聽來自客戶端的Socket鏈接,如果沒有鏈接,它將一直等待。如果接收到一個客戶端Socket的連接請求,ServerSocket的accept()方法將返回一個與客戶端Socket對應的Socket(每個TCP連接有兩個Socket),否則該方法將一直阻塞,線程也被阻塞。

服務端思路:服務端應該包含多個線程,每個Socket對應一個線程,這個線程負責讀取該Socket對應輸入流的數據(從客戶端發(fā)送過來的數據),并將讀到的數據向每個Socket輸出流發(fā)送一次(將一個客戶端發(fā)送過來的數據“廣播”給其他客戶端)。

服務端代碼:

//服務端主類
public class MyServer
{
  public static List<Socket> socketList = Collections.synchronizedList(new ArrayList<Socket>());
  public static void main(String[] args) throws IOException
  {
    ServerSocket ss = new ServerSocket(30000);
    while (true)
    {
      //此行代碼會阻塞,將一直等待別人的連接
      Socket s = ss.accept();
      socketList.add(s);
      //每當客戶端連接后啟動一個ServerThread線程為該客戶端服務
      new Thread(new ServerThread(s)).start();
    }
  }
}

public class ServerThread implements Runnable
{
  //定義當前線程所處理的Socket
  Socket s = null;
  //該線程所處理的Socket對應的輸入流
  BufferedReader br = null;
  public ServerThread(Socket s) throws IOException
  {
    this.s = s;
    //初始化該Socket對應的輸入流
    br = new BufferedReader(new InputStreamReader(s.getInputStream()));
  }

  @Override
  public void run()
  {
    try
    {
      String content = null;
      //采用循環(huán)不斷地從Socket中讀取客戶端發(fā)送來的數據
      while ((content = readFromClient()) != null)
      {
        //遍歷socketList中的每個Socket
        //將讀到的內容向每個Socket發(fā)送一次
        for (Socket s : MyServer.socketList)
        {
          PrintStream ps = new PrintStream(s.getOutputStream());
          ps.println(content);
        }
      }
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }

  //定義讀取客戶端數據的方法
  private String readFromClient()
  {
    try
    {
      return br.readLine();
    }
    //如果捕獲到異常,則表明該Socket對應的客戶端已經關閉
    catch (IOException e)
    {
      //刪除該Socket
      MyServer.socketList.remove(s);
    }
    return null;
  }
}

客戶端思路:將用戶輸入的數據寫入Socket對應的輸入流中;開啟一個子線程讀取Socket對應輸入流中的數據(從服務端發(fā)送過來的數據),并通過Handler將讀取的數據發(fā)送到主線程來更新UI。

//用戶界面Activity
public class MainActivity extends Activity
{
  private EditText mReceiverMsg;
  private Button mSendBtn;
  private EditText mSendMsg;
  Handler handler = new Handler()
  {
    @Override
    public void handleMessage(Message msg)
    {
      Log.d("mainActivity" , "okk");
      mReceiverMsg.append(msg.obj.toString());
    }
  };
  private Socket s;
  @Override
  protected void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);

    initView();
    initSocket();
    mSendBtn.setOnClickListener(new View.OnClickListener()
    {
      @Override
      public void onClick(View view)
      {
        sendData();
      }
    });
  }

  private void initSocket()
  {
    new Thread()
    {
      @Override
      public void run()
      {
        try
        {
          s = new Socket("192.168.1.101" , 30000);
          new Thread(new ClientThread(s , handler)).start();
        }
        catch (IOException e)
        {
          e.printStackTrace();
        }
      }
    }.start();
  }

  private void initView()
  {
    mReceiverMsg = (EditText) findViewById(R.id.receiver_message);
    mSendMsg = (EditText) findViewById(R.id.send_message);
    mSendBtn = (Button) findViewById(R.id.send_button);
  }

  private void sendData()
  {
    try
    {
      //獲取該Socket對應的輸出流
      PrintStream ps = new PrintStream(s.getOutputStream());
      if (TextUtils.isEmpty(mSendMsg.getText()))
      {
        Toast.makeText(this , "請輸入信息" , Toast.LENGTH_LONG).show();
        return;
      }
      ps.println(mSendMsg.getText().toString());
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }
}

public class ClientThread implements Runnable
{
  //該線程負責處理的Socket
  private Socket ss;
  //該線程所處理的Socket對應的輸入流
  BufferedReader br = null;
  Handler handler;
  public ClientThread(Socket s , Handler handler) throws IOException
  {
    this.ss = s;
    this.handler = handler;
    br = new BufferedReader(new InputStreamReader(ss.getInputStream()));
  }

  @Override
  public void run()
  {
    try
    {
      String content = null;
      while ((content = br.readLine()) != null)
      {
        Message msg = new Message();
        msg.obj = content;
        handler.sendMessage(msg);
      }

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

先運行上面程序中的MyServer類,該類運行只是作為服務端。再啟動多個模擬器,運行安裝客戶端的程序作為多個客戶端,然后可以再任何一個客戶端通過Edit輸入一些內容,點擊發(fā)送就可以在任何一個客戶端看到剛剛輸入的內容。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節(jié)

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

AI