Java如何实现多线程聊天应用程序?S2(客户端编程)

2021年3月27日14:19:10 发表评论 937 次浏览

先决条件:在套接字编程中引入线程, 多线程聊天应用程序|S1

本文提供了多线程聊天应用程序的客户端程序的实现。到目前为止, 套接字编程中的所有示例都假定客户端首先发送一些信息, 然后服务器或其他客户端对该信息作出响应。

在现实世界中,情况可能并非如此。为了能够接收到信息,并不需要向某人发送信息。客户端应该随时接收到发送到它的消息,即发送和接收必须作为单独的活动来实现,而不是连续的。

有一个非常简单的解决方案, 它使用线程来实现此功能。在客户端实现中, 我们将创建两个线程:

SendMessage:该线程将用于将消息发送给其他客户端。工作非常简单, 它需要输入消息发送和接收者来传递。请注意, 此实现假定消息的格式为讯息#收件人, 其中收件人是收件人的名称。然后, 它将消息写在其输出流上, 该输出流连接到该客户端的处理程序。处理程序破坏消息和收件人部分, 然后传递给特定的收件人。让我们看一下如何实现此线程。

Thread sendMessage = new Thread(new Runnable() {
  @Override
  public void run() {
      while (true) {

          // read the message to deliver.
          String msg = sc.nextLine();
          try {

              // write on the output stream
              dos.writeUTF(msg);
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
  }
});

readMessage:采用类似的方法来创建用于接收消息的线程。当任何客户端尝试在此客户端输入流上写入时, 我们使用readUTF()方法读取该消息。下面显示了如何实现此线程的以下代码段:

Thread readMessage = new Thread(new Runnable() {
  
  @Override
  public void run() {

      while (true) {
          try {

              // read the message sent to this client
              String msg = dis.readUTF();
              System.out.println(msg);
          } catch (IOException e) {

              e.printStackTrace();
          }
      }
  }
});

客户端编程的其余步骤与前面的示例相似。简要说明如下-

  1. 建立套接字连接
  2. 通讯
    在readMessage和sendMessage线程的帮助下进行通信。用于读取和写入的单独线程可确保同时发送和接收消息。
// Java implementation for multithreaded chat client
// Save file as Client.java
  
import java.io.*;
import java.net.*;
import java.util.Scanner;
  
public class Client 
{
     final static int ServerPort = 1234 ;
  
     public static void main(String args[]) throws UnknownHostException, IOException 
     {
         Scanner scn = new Scanner(System.in);
          
         // getting localhost ip
         InetAddress ip = InetAddress.getByName( "localhost" );
          
         // establish the connection
         Socket s = new Socket(ip, ServerPort);
          
         // obtaining input and out streams
         DataInputStream dis = new DataInputStream(s.getInputStream());
         DataOutputStream dos = new DataOutputStream(s.getOutputStream());
  
         // sendMessage thread
         Thread sendMessage = new Thread( new Runnable() 
         {
             @Override
             public void run() {
                 while ( true ) {
  
                     // read the message to deliver.
                     String msg = scn.nextLine();
                      
                     try {
                         // write on the output stream
                         dos.writeUTF(msg);
                     } catch (IOException e) {
                         e.printStackTrace();
                     }
                 }
             }
         });
          
         // readMessage thread
         Thread readMessage = new Thread( new Runnable() 
         {
             @Override
             public void run() {
  
                 while ( true ) {
                     try {
                         // read the message sent to this client
                         String msg = dis.readUTF();
                         System.out.println(msg);
                     } catch (IOException e) {
  
                         e.printStackTrace();
                     }
                 }
             }
         });
  
         sendMessage.start();
         readMessage.start();
  
     }
}

输出:

从客户端0:

hello#client 1
client 1 : heya
how are you#client 1
client 1 : fine..how about you
logout

从客户1:

client 0 : hello
heya#client 0
client 0 : how are you
fine..how about you#client 0
logout

重要事项:

  • 要从任何客户端发送消息, 请键入消息, 后跟"#", 然后输入接收方客户端的名称。请注意, 此实现将名称命名为"客户端0", "客户端1" ...."客户端n", 因此必须在名称末尾附加名称。之后, 按Enter键。
  • 发送消息后, 此客户端的处理程序将收到该消息, 并将其传递到指定的客户端。
  • 如果有任何客户端向该客户端发送消息, 则readMessage线程将自动在控制台上打印该消息。
  • 客户端完成聊天后, 他可以发送"注销"消息而没有任何收件人名称, 以便服务器知道该客户端已注销系统。建议关闭客户端之前发送注销消息, 以避免任何错误。

如何运行以上程序?

与前面的示例类似, 首先运行服务器, 然后运行客户端的多个实例。从每个客户端, 尝试相互发送消息。请确保仅将邮件发送到有效客户端, 即发送到活动列表中可用的客户端。

建议改进

这只是关于如何使用线程和套接字编程来创建功能强大的程序的解释部分。对于感兴趣的读者, 建议对上述实现进行一些改进,

  • 为客户端创建用于发送和接收消息的图形用户界面。可以使用诸如Netbeans之类的工具来快速设计接口
  • 当前, 名称被硬编码为客户端0, 客户端1。这可以进行改进以使用用户给定的昵称。
  • 可以进一步增强此实现, 以向客户端提供当前活动用户的列表, 以便他可以知道他的所有朋友在线谁。为此可以实现一个简单的方法, 该方法在被调用时将在活动列表中打印名称。

如果发现任何不正确的地方, 或者想分享有关上述主题的更多信息, 请写评论。

木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: