使用Java和Eclipse,我试图用一个服务器和多个客户端实现一个聊天室应用程序。下图所示的服务器将为每个与其连接的客户端提供一个线程。另一个用于接受连接的线程,另一个用于使用当前连接的客户端数量更新标签。 我遇到的问题是我不知道如何继续向聊天室中的某人发送特定消息。目前,它正在发送给所有人。有什么方法可以向聊天室中有特定名字的人发送消息吗? 我正在使用的三个类如下。
import java.io.*;
import java.net.*;
import java.util.ArrayList;
public class clientThread extends Thread{
//the ClientServiceThread class extends the Thread class and has the following parameters
public int number; //client name
public Socket connectionSocket; //client connection socket
ArrayList<clientThread> Clients; //list of all clients connected to the server
//constructor function
public clientThread(int number, Socket connectionSocket, ArrayList<clientThread> Clients) {
this.number = number;
this.connectionSocket = connectionSocket;
this.Clients = Clients;
}
//thread's run function
public void run() {
try {
//create a buffer reader and connect it to the client's connection socket
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));;
String clientSentence;
DataOutputStream outToClient;
//always read messages from client
while (true) {
clientSentence = inFromClient.readLine();
//ckeck the start of the message
if (clientSentence.startsWith("-Remove")) { //Remove Client
for (int i = 0; i < Clients.size(); i++) {
if (Clients.get(i).number == number) {
Clients.remove(i);
}
}
}
else if (clientSentence.startsWith("-getName"))
{
for (int i = 0; i < Clients.size(); i++) {
String name = clientSentence;
outToClient = new DataOutputStream(Clients.get(i).connectionSocket.getOutputStream());
outToClient.writeBytes("-sendName," +name+ "\n");
}
}
else if (clientSentence.startsWith("-getMessage"))
{
for (int j = 0; j < Clients.size(); j++) {
String message = clientSentence;
outToClient = new DataOutputStream(Clients.get(j).connectionSocket.getOutputStream());
outToClient.writeBytes("-sendMessage," +message+ "\n");
}
}
}
} catch(Exception ex) {
}
}
}
下面的类服务器信息
import java.awt.Color;
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Server {
//Array of type ClientServiceThread, for all connected clients
public static ArrayList<clientThread> Clients = new ArrayList<clientThread>();
static int clientCount = 0;
public static void main(String[] args) throws Exception {
//Create the GUI frame and components
JFrame frame = new JFrame ("Chatting Server");
frame.setLayout(null);
frame.setBounds(100, 100, 300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel connectionStatusLabel = new JLabel("No Clients Connected");
connectionStatusLabel.setBounds(80, 30, 200, 30);
connectionStatusLabel.setForeground(Color.red);
frame.getContentPane().add(connectionStatusLabel);
//create the welcoming server's socket
ServerSocket welcomeSocket = new ServerSocket(6789);
//thread to always listen for new connections from clients
new Thread (new Runnable(){ @Override
public void run() {
Socket connectionSocket;
DataOutputStream outToClient;
while (!welcomeSocket.isClosed()) {
try {
//when a new client connect, accept this connection and assign it to a new connection socket
connectionSocket = welcomeSocket.accept();
//create a new output stream and send the message "You are connected" to the client
outToClient = new DataOutputStream(connectionSocket.getOutputStream());
outToClient.writeBytes("-Connected\n");
clientCount++;
//add the new client to the client's array
Clients.add(new clientThread(clientCount, connectionSocket, Clients));
//start the new client's thread
Clients.get(Clients.size() - 1).start();
}
catch (Exception ex) {
}
}
}}).start();
//thread to always get the count of connected clients and update the label and send to clients
new Thread (new Runnable(){ @Override
public void run() {
try {
DataOutputStream outToClient;
while (true) {
if (Clients.size() > 0) //if there are one or more clients print their number
{
if (Clients.size() == 1)
connectionStatusLabel.setText("1 Client Connected");
else
connectionStatusLabel.setText(Clients.size() + " Clients Connected");
connectionStatusLabel.setForeground(Color.blue);
}
else { //if there are no clients connected, print "No Clients Connected"
connectionStatusLabel.setText("No Clients Connected");
connectionStatusLabel.setForeground(Color.red);
}
for (int i = 0; i < Clients.size(); i++) {
outToClient = new DataOutputStream(Clients.get(i).connectionSocket.getOutputStream());
outToClient.writeBytes("-Count, " + Clients.size() + "\n");
}
Thread.sleep(1000);
}
} catch (Exception ex) {
}
}}).start();
frame.setVisible(true);
}
}
在下面分类客户信息
import java.io.*;
import java.net.*;
import javax.swing.*;
import java.awt.Color;
import java.awt.event.*;
public class Client {
static Socket clientSocket;
static JLabel sendLabel;
static JTextArea receivedTextArea;
public static void main(String[] args) throws Exception {
//Create the GUI frame and components
JFrame frame = new JFrame ("Chatting Client");
frame.setLayout(null);
frame.setBounds(100, 100, 500, 550);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel clientLabel = new JLabel("Client Name");
clientLabel.setBounds(20, 40, 150, 30);
frame.getContentPane().add(clientLabel);
JTextField nameTextField = new JTextField();
nameTextField.setBounds(130, 40, 150, 30);
frame.getContentPane().add(nameTextField);
JButton connectButton = new JButton("Connect");
connectButton.setBounds(290, 40, 100, 30);
frame.getContentPane().add(connectButton);
receivedTextArea = new JTextArea();
receivedTextArea.setBounds(20,80, 460, 300);
receivedTextArea.setEditable(false);
frame.getContentPane().add(receivedTextArea);
JScrollPane receivedTextAreaScroll = new JScrollPane(receivedTextArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
receivedTextAreaScroll.setBounds(20, 80, 460, 300);
frame.getContentPane().add(receivedTextAreaScroll);
sendLabel = new JLabel("Send to");
sendLabel.setBounds(20, 400, 100, 30);
frame.getContentPane().add(sendLabel);
sendLabel.setVisible(false);
JTextField sendTextField = new JTextField();
sendTextField.setBounds(130, 400, 150, 30);
frame.getContentPane().add(sendTextField);
sendTextField.setVisible(false);
JTextField messageTextField = new JTextField();
messageTextField.setBounds(20, 450, 350, 60);
frame.getContentPane().add(messageTextField);
messageTextField.setVisible(false);
JButton sendButton = new JButton("Send");
sendButton.setBounds(400, 450, 80, 30);
frame.getContentPane().add(sendButton);
sendButton.setVisible(false);
//Action listener when connect button is pressed
connectButton.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e)
{
try {
if (connectButton.getText().equals("Connect") && !nameTextField.getText().isEmpty()) { //if pressed to connect
//create a new socket to connect with the server application
clientSocket = new Socket ("localhost", 6789);
//call function StartThread
StartThread();
//make the GUI components visible, so the client can send and receive messages
sendButton.setVisible(true);
sendLabel.setVisible(true);
sendTextField.setVisible(true);
messageTextField.setVisible(true);
receivedTextArea.setText("You are Connected \n");
//change the Connect button text to disconnect
connectButton.setText("Disconnect");
//create an output stream
DataOutputStream outToServer = new DataOutputStream (clientSocket.getOutputStream());
if (!nameTextField.getText().equals("")) {
String sendingName = "-getName," + nameTextField.getText() + "\n";
outToServer.writeBytes(sendingName);
}
} else { //if pressed to disconnect
//create an output stream and send a Remove message to disconnect from the server
DataOutputStream outToServer = new DataOutputStream (clientSocket.getOutputStream());
outToServer.writeBytes("-Remove\n");
//close the client's socket
clientSocket.close();
//make the GUI components invisible
sendButton.setVisible(false);
sendLabel.setVisible(false);
sendTextField.setVisible(false);
messageTextField.setVisible(false);
receivedTextArea.setText(null);
//change the Connect button text to connect
connectButton.setText("Connect");
}
} catch (Exception ex) {
System.out.println(ex.toString());
}
}});
//Action listener when send button is pressed
sendButton.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e)
{
try {
//create an output stream
DataOutputStream outToServer = new DataOutputStream (clientSocket.getOutputStream());
if (!messageTextField.getText().equals("")) {
String sendingMessage = "-getMessage," + messageTextField.getText() + "\n";
outToServer.writeBytes(sendingMessage);
}
} catch (Exception ex) {
System.out.println(ex.toString());
}
}});
//Disconnect on close
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
try {
//create an output stream and send a Remove message to disconnect from the server
DataOutputStream outToServer = new DataOutputStream (clientSocket.getOutputStream());
outToServer.writeBytes("-Remove\n");
//close the client's socket
clientSocket.close();
//make the GUI components invisible
sendButton.setVisible(false);
sendLabel.setVisible(false);
sendTextField.setVisible(false);
messageTextField.setVisible(false);
receivedTextArea.setText(null);
//change the Connect button text to connect
connectButton.setText("Connect");
System.exit(0);
} catch (Exception ex) {
System.out.println(ex.toString());
}
}
});
frame.setVisible(true);
}
//Thread to always read messages from the server and print them in the textArea
private static void StartThread() {
new Thread (new Runnable(){ @Override
public void run() {
try {
//create a buffer reader and connect it to the socket's input stream
BufferedReader inFromServer = new BufferedReader (new InputStreamReader(clientSocket.getInputStream()));
String receivedSentence;
//always read received messages and append them to the textArea
while (true) {
receivedSentence = inFromServer.readLine();
String printName = receivedSentence;
//System.out.println(receivedSentence);
if (receivedSentence.startsWith("-sendName"))
{
receivedTextArea.append(printName+ " is connected \n");
}
else if (receivedSentence.startsWith("-sendMessage"))
{
String printMessage = receivedSentence;
receivedTextArea.append(printMessage+ "\n");
}
}
}
catch(Exception ex) {
}
}}).start();
}
}