Java中的多线程聊天应用程序|第 2 组(客户端编程)
先决条件:socket编程中引入线程,多线程聊天应用|设置 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(); } } } });
- 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(); } } } });
客户端编程的其余步骤与前面的示例类似。简要说明如下——
- 建立套接字连接
- 沟通
在 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。这可以改进为使用用户给定的昵称。
- 可以进一步增强此实现以向客户端提供当前活跃用户的列表,以便他可以知道他所有的朋友都在线。可以为此目的实现一个简单的方法,当调用它时打印活动列表中的名称。