更新双向 java 信使聊天以允许多个用户
Updating a two-way java messenger chat to allow multiplie users
我刚刚完成了关于创建即时消息聊天的 youtube series,它通过套接字在服务器和一个客户端之间工作。但是,我想改进此聊天,以便多个客户端可以同时连接。
服务器工作正常,第一个客户端也是。在我打开的第一个客户端 window 上,我收到消息:
Attempting connection...
Connected to 127.0.0.1
Streams are now setup!
SERVER - You are now connected!
但是在第二个客户端 window 我打开,流没有设置,我只收到以下消息
Attempting connection...
Connected to 127.0.0.1
我听说我需要多线程来解决这个问题,但是我不太确定我该怎么做。
这些是我的文件:
ChatServerTest
import javax.swing.JFrame;
public class ChatServerTest {
public static void main(String[] args) {
ChatServer server = new ChatServer();
server.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
server.startRunning();
}
}
ChatServer
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ChatServer extends JFrame {
private JTextField userText;
private JTextArea chatWindow;
private ObjectOutputStream output;
private ObjectInputStream input;
private ServerSocket server;
private Socket connection;
int port = 1234; // Test port
//constructor (GUI)
public ChatServer() {
super("Instant Messenger (Server)");
userText = new JTextField();
userText.setEditable(false);
userText.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent event){
sendMessage(event.getActionCommand());
userText.setText("");
}
}
);
add(userText, BorderLayout.NORTH);
chatWindow = new JTextArea();
add(new JScrollPane(chatWindow));
setSize(300,150);
setVisible(true);
}
//set up and run the server
public void startRunning(){
try{
server = new ServerSocket(port);
while(true){
try{
waitForConnection();
setupStreams();
whileChatting();
}catch(EOFException eofException){
showMessage("\nServer ended the connection!");
}finally{
closeCrap();
}
}
}catch(IOException ioException){
ioException.printStackTrace();
}
}
//wait for connection, then display connection information
private void waitForConnection() throws IOException{
showMessage("Waiting for someone to connect... \n");
connection = server.accept();
showMessage("Now connected to " + connection.getInetAddress().getHostName());
}
//get stream to send and receive data
private void setupStreams() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showMessage("\nStreams are now setup!\n");
}
//during the chat conversation
private void whileChatting() throws IOException{
String message = "You are now connected!";
sendMessage(message);
ableToType(true);
do{
try{
message = (String) input.readObject();
showMessage("\n" + message);
}catch(ClassNotFoundException classNotFoundException){
showMessage("\nERROR: Not a string");
}
}while(!message.equals("CLIENT - END"));
}
private void closeCrap(){
showMessage("\nClosing connections...\n");
ableToType(false);
try{
output.close();
input.close();
connection.close();
}catch(IOException ioException){
ioException.printStackTrace();
}
}
//send a message to client
private void sendMessage(String message) {
try{
output.writeObject("SERVER - " + message);
output.flush();
showMessage("\nSERVER - " + message);
}catch(IOException ioExcenption){
chatWindow.append("\nERROR: Can't send message");
}
}
//updates chatWindow
private void showMessage(final String text){
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
chatWindow.append(text);
}
}
);
}
//let the user type stuff into their box
private void ableToType(final boolean tof) {
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
userText.setEditable(tof);
}
}
);
}
}
ChatClientTest
import javax.swing.JFrame;
public class ChatClientTest {
public static void main(String[] args) {
String IP = "127.0.0.1";
ChatClient client;
client = new ChatClient(IP);
client.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.startRunning();
}
}
ChatClient
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ChatClient extends JFrame {
private JTextField userText;
private JTextArea chatWindow;
private ObjectOutputStream output;
private ObjectInputStream input;
private String message = "";
private String serverIP;
private Socket connection;
int port = 1234; // Test port
//constructor
public ChatClient(String host){
super("Instant Messenger (Client)");
serverIP = host;
userText = new JTextField();
userText.setEditable(false);
userText.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent event){
sendMessage(event.getActionCommand());
userText.setText("");
}
}
);
add(userText, BorderLayout.NORTH);
chatWindow = new JTextArea();
add(new JScrollPane(chatWindow), BorderLayout.CENTER);
setSize(300, 150);
setVisible(true);
}
//connect to server
public void startRunning(){
try{
connectToServer();
setupStreams();
whileChatting();
}catch(EOFException eofException){
showMessage("\nClient terminated connection.");
}catch(IOException ioException){
ioException.printStackTrace();
}finally{
closeCrap();
}
}
//connect to server
private void connectToServer() throws IOException{
showMessage("Attempting connection...\n");
connection = new Socket(InetAddress.getByName(serverIP), port);
showMessage("Connected to " + connection.getInetAddress().getHostName());
}
//set up streams to send and receive messages
private void setupStreams() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showMessage("\nStreams are now setup!");
}
//while chatting with server
private void whileChatting() throws IOException{
ableToType(true);
do{
try{
message = (String) input.readObject();
showMessage("\n" + message);
}catch(ClassNotFoundException classNotFoundException){
showMessage("\nUnknown object type");
}
}while(!message.equals("SERVER - END"));
}
//close the streams and sockets
private void closeCrap(){
showMessage("\nClosing down...");
ableToType(false);
try{
output.close();
input.close();
connection.close();
}catch(IOException ioException){
ioException.printStackTrace();
}
}
//send messages to server
private void sendMessage(String message){
try{
output.writeObject("CLIENT - " + message);
output.flush();
showMessage("\nCLIENT - " + message);
}catch(IOException ioException){
chatWindow.append("\nMessage failed to send.");
}
}
//change/update chatWindow
private void showMessage(final String message){
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
chatWindow.append(message);
}
}
);
}
//gives user permission to type text into the text box
private void ableToType(final boolean tof){
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
userText.setEditable(tof);
}
}
);
}
}
提前感谢并感谢我能得到的任何回复:)
虽然对于 SO 来说有点过于宽泛,但我将为您提供一个如何处理此类服务器-客户端程序的策略。如需更多信息,只需点击您最喜欢的搜索机即可。一定有很多文章。
一个服务器处理多个客户端请求的基本策略是这样的:
while (true) {
accept a connection;
create a thread to deal with the client;
start that thread;
}
这样,新创建(和启动)的线程将 运行 并发。这让线程 运行ning 此服务器代码返回到 while (true)
循环并停止在 "accept a connection" 行,有效地等待下一个客户端。
所以,基本上你应该有这样的东西
while (true) {
connection = server.accept();
Thread clientHandler = new Thread(new ClientHandler(connection));
clientHandler.start();
}
这需要一个 class ClientHandler
实现 Runnable
来完成所有客户端通信。
请注意,您的程序中有许多部分需要重构。您的 class ChatServer
做的工作太多了。它甚至在扩展 JFrame
。我的建议在同一个联盟中发挥作用,只是一个开始路径。通常,您不应该为每个传入的客户端请求创建一个新线程,而是使用一个有限的线程池。
我刚刚完成了关于创建即时消息聊天的 youtube series,它通过套接字在服务器和一个客户端之间工作。但是,我想改进此聊天,以便多个客户端可以同时连接。
服务器工作正常,第一个客户端也是。在我打开的第一个客户端 window 上,我收到消息:
Attempting connection...
Connected to 127.0.0.1
Streams are now setup!
SERVER - You are now connected!
但是在第二个客户端 window 我打开,流没有设置,我只收到以下消息
Attempting connection...
Connected to 127.0.0.1
我听说我需要多线程来解决这个问题,但是我不太确定我该怎么做。
这些是我的文件:
ChatServerTest
import javax.swing.JFrame;
public class ChatServerTest {
public static void main(String[] args) {
ChatServer server = new ChatServer();
server.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
server.startRunning();
}
}
ChatServer
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ChatServer extends JFrame {
private JTextField userText;
private JTextArea chatWindow;
private ObjectOutputStream output;
private ObjectInputStream input;
private ServerSocket server;
private Socket connection;
int port = 1234; // Test port
//constructor (GUI)
public ChatServer() {
super("Instant Messenger (Server)");
userText = new JTextField();
userText.setEditable(false);
userText.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent event){
sendMessage(event.getActionCommand());
userText.setText("");
}
}
);
add(userText, BorderLayout.NORTH);
chatWindow = new JTextArea();
add(new JScrollPane(chatWindow));
setSize(300,150);
setVisible(true);
}
//set up and run the server
public void startRunning(){
try{
server = new ServerSocket(port);
while(true){
try{
waitForConnection();
setupStreams();
whileChatting();
}catch(EOFException eofException){
showMessage("\nServer ended the connection!");
}finally{
closeCrap();
}
}
}catch(IOException ioException){
ioException.printStackTrace();
}
}
//wait for connection, then display connection information
private void waitForConnection() throws IOException{
showMessage("Waiting for someone to connect... \n");
connection = server.accept();
showMessage("Now connected to " + connection.getInetAddress().getHostName());
}
//get stream to send and receive data
private void setupStreams() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showMessage("\nStreams are now setup!\n");
}
//during the chat conversation
private void whileChatting() throws IOException{
String message = "You are now connected!";
sendMessage(message);
ableToType(true);
do{
try{
message = (String) input.readObject();
showMessage("\n" + message);
}catch(ClassNotFoundException classNotFoundException){
showMessage("\nERROR: Not a string");
}
}while(!message.equals("CLIENT - END"));
}
private void closeCrap(){
showMessage("\nClosing connections...\n");
ableToType(false);
try{
output.close();
input.close();
connection.close();
}catch(IOException ioException){
ioException.printStackTrace();
}
}
//send a message to client
private void sendMessage(String message) {
try{
output.writeObject("SERVER - " + message);
output.flush();
showMessage("\nSERVER - " + message);
}catch(IOException ioExcenption){
chatWindow.append("\nERROR: Can't send message");
}
}
//updates chatWindow
private void showMessage(final String text){
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
chatWindow.append(text);
}
}
);
}
//let the user type stuff into their box
private void ableToType(final boolean tof) {
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
userText.setEditable(tof);
}
}
);
}
}
ChatClientTest
import javax.swing.JFrame;
public class ChatClientTest {
public static void main(String[] args) {
String IP = "127.0.0.1";
ChatClient client;
client = new ChatClient(IP);
client.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.startRunning();
}
}
ChatClient
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ChatClient extends JFrame {
private JTextField userText;
private JTextArea chatWindow;
private ObjectOutputStream output;
private ObjectInputStream input;
private String message = "";
private String serverIP;
private Socket connection;
int port = 1234; // Test port
//constructor
public ChatClient(String host){
super("Instant Messenger (Client)");
serverIP = host;
userText = new JTextField();
userText.setEditable(false);
userText.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent event){
sendMessage(event.getActionCommand());
userText.setText("");
}
}
);
add(userText, BorderLayout.NORTH);
chatWindow = new JTextArea();
add(new JScrollPane(chatWindow), BorderLayout.CENTER);
setSize(300, 150);
setVisible(true);
}
//connect to server
public void startRunning(){
try{
connectToServer();
setupStreams();
whileChatting();
}catch(EOFException eofException){
showMessage("\nClient terminated connection.");
}catch(IOException ioException){
ioException.printStackTrace();
}finally{
closeCrap();
}
}
//connect to server
private void connectToServer() throws IOException{
showMessage("Attempting connection...\n");
connection = new Socket(InetAddress.getByName(serverIP), port);
showMessage("Connected to " + connection.getInetAddress().getHostName());
}
//set up streams to send and receive messages
private void setupStreams() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showMessage("\nStreams are now setup!");
}
//while chatting with server
private void whileChatting() throws IOException{
ableToType(true);
do{
try{
message = (String) input.readObject();
showMessage("\n" + message);
}catch(ClassNotFoundException classNotFoundException){
showMessage("\nUnknown object type");
}
}while(!message.equals("SERVER - END"));
}
//close the streams and sockets
private void closeCrap(){
showMessage("\nClosing down...");
ableToType(false);
try{
output.close();
input.close();
connection.close();
}catch(IOException ioException){
ioException.printStackTrace();
}
}
//send messages to server
private void sendMessage(String message){
try{
output.writeObject("CLIENT - " + message);
output.flush();
showMessage("\nCLIENT - " + message);
}catch(IOException ioException){
chatWindow.append("\nMessage failed to send.");
}
}
//change/update chatWindow
private void showMessage(final String message){
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
chatWindow.append(message);
}
}
);
}
//gives user permission to type text into the text box
private void ableToType(final boolean tof){
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
userText.setEditable(tof);
}
}
);
}
}
提前感谢并感谢我能得到的任何回复:)
虽然对于 SO 来说有点过于宽泛,但我将为您提供一个如何处理此类服务器-客户端程序的策略。如需更多信息,只需点击您最喜欢的搜索机即可。一定有很多文章。
一个服务器处理多个客户端请求的基本策略是这样的:
while (true) {
accept a connection;
create a thread to deal with the client;
start that thread;
}
这样,新创建(和启动)的线程将 运行 并发。这让线程 运行ning 此服务器代码返回到 while (true)
循环并停止在 "accept a connection" 行,有效地等待下一个客户端。
所以,基本上你应该有这样的东西
while (true) {
connection = server.accept();
Thread clientHandler = new Thread(new ClientHandler(connection));
clientHandler.start();
}
这需要一个 class ClientHandler
实现 Runnable
来完成所有客户端通信。
请注意,您的程序中有许多部分需要重构。您的 class ChatServer
做的工作太多了。它甚至在扩展 JFrame
。我的建议在同一个联盟中发挥作用,只是一个开始路径。通常,您不应该为每个传入的客户端请求创建一个新线程,而是使用一个有限的线程池。