📜  Java中的多线程聊天应用程序|第 2 组(客户端编程)

📅  最后修改于: 2022-05-13 01:54:27.263000             🧑  作者: Mango

Java中的多线程聊天应用程序|第 2 组(客户端编程)

先决条件:socket编程中引入线程,多线程聊天应用|设置 1

本文给出了多线程聊天应用程序的客户端程序的实现。到目前为止,套接字编程中的所有示例都假设客户端首先发送一些信息,然后服务器或其他客户端响应该信息。
在现实世界中,情况可能并非如此。无需向某人发送消息即可接收消息。每当消息传递给客户端时,客户端应该很容易接收消息,即发送和接收必须作为单独的活动而不是顺序来实现
有一个非常简单的解决方案,它使用线程来实现此功能。在客户端实现中,我们将创建两个线程:

  1. SendMessage :该线程将用于向其他客户端发送消息。工作非常简单,只需输入要发送的消息和要发送到的收件人。请注意,此实现假定消息的格式为message # recipient ,其中接收者是接收者的姓名。然后它将消息写入连接到该客户端的处理程序的输出流上。处理程序中断消息和收件人部分并传递给特定收件人。让我们看看这个线程是如何实现的。
    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();
                        }
                    }
                }
            });
    
  2. 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

要点:

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

如何运行上述程序?

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

建议的改进

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

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