当用户决定按退出按钮关闭该应用程序时,我想提示如何对聊天应用程序的客户端进行编程-当前在服务器上将发生的情况将是输出连接丢失;表示应用程序已关闭,但客户端与服务器之间的套接字仍处于打开状态。
因此,如果用户存在jframe,我想如何编程,我的程序应自动将客户端与服务器断开连接(关闭将两者连接在一起的端口)。
这是我的客户端类的源代码,请告诉我是否有人已经问过这个问题,并在可能的情况下提供链接:
import java.net.*;
import java.io.*;
import java.util.*;
/**
* This is a chat application, a prototype of a distributed system
* that exchanges messages using the TCP protocol in the client-server
* network architecture for multiple clients that are connected.
*/
public class TCP_Client extends javax.swing.JFrame {
String username;
String address = "localhost";
ArrayList<String> Users = new ArrayList<>();
int port_no = 1183;
Boolean isConnected = false;
Socket Connection_Socket; // Part of communication channel
BufferedReader in_From_User; // Data buffer from server
PrintWriter out_To_Server; // Format data as text (UTF-8)
/* Constructor to initialise the interface for client frame */
public TCP_Client() {
initComponents();
Chat_LogC.setEditable(false);
}
/* Thread that listens for incoming response(s) from the server */
public void ListenThread() {
Thread IncomingReader = new Thread(new Listen_Server());
IncomingReader.start();
}
/* Add new user into array of connected clients */
public void New_User(String U_name) {
Users.add(U_name);
}
/* Remove user from array of connected clients */
public void Remove_User(String U_name) {
Chat_LogC.append(U_name + " is offline \n");
}
/* Method for number of connected clients - no limit to size */
public void Write_Users() {
String[] temp = new String[(Users.size())];
Users.toArray(temp);
Chat_LogC.append("Online Users: " + Users.toString() + "\n");
}
/* Method for request upon client disconnect from the server */
public void Req_Disconnect() {
String leaving = (username + ": :Disconnect");
try {
out_To_Server.println(leaving);
out_To_Server.flush(); //flushes the buffer
} catch (Exception ex) {
Chat_LogC.append("Failed to send request to Disconnect \n");
}
}
/* Client is no longer connected to the chat room (server) */
public void Disconnect() {
try {
Chat_LogC.append(username + " has Disconnected \n");
Connection_Socket.close();
} catch (Exception ex) {
Chat_LogC.append("Failed to disconnect \n");
}
isConnected = false;
Username_txt.setEditable(true);
Password_txt.setEditable(true);
}
/**
* Listener class that implements runnable interface for communicating
* with the chat server.
*/
public class Listen_Server implements Runnable {
@Override
public synchronized void run() {
String[] msg_data;
String stream;
String Success = "Done";
String Connect = "Connect";
String Disconnect = "Disconnect";
String chat = "Chat";
try {
while ((stream = in_From_User.readLine()) != null) {
msg_data = stream.split(":"); // Split string into substrings
if (msg_data[2].equals(chat)) {
Chat_LogC.append(msg_data[0] + ": " + msg_data[1] + "\n");
Chat_LogC.setCaretPosition(Chat_LogC.getDocument().getLength());
} else if (msg_data[2].equals(Connect)) {
Chat_LogC.removeAll();
New_User(msg_data[0]);
} else if (msg_data[2].equals(Disconnect)) {
Remove_User(msg_data[0]);
} else if (msg_data[2].equals(Success)) {
Write_Users();
Users.clear();
}
}
} catch (Exception ex) {}
}
}
/* Generated code that can be modified in JFrame */
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
Address_lbl = new javax.swing.JLabel();
Port_Number_lbl = new javax.swing.JLabel();
Username_lbl = new javax.swing.JLabel();
Username_txt = new javax.swing.JTextField();
Password_lbl = new javax.swing.JLabel();
Password_txt = new javax.swing.JTextField();
Connect_Btn = new javax.swing.JButton();
Disconnect_Btn = new javax.swing.JButton();
jScrollPane1 = new javax.swing.JScrollPane();
Chat_LogC = new javax.swing.JTextArea();
dialogue_txt = new javax.swing.JTextField();
Send_Btn = new javax.swing.JButton();
localhost_lbl = new javax.swing.JLabel();
port_no_lbl = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("Client Frame");
setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
setName("client"); // NOI18N
setResizable(false);
Address_lbl.setText("Address: ");
Port_Number_lbl.setText("Port number:");
Username_lbl.setText("Username:");
Username_txt.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Username_txtActionPerformed(evt);
}
});
Password_lbl.setText("Password: ");
Password_txt.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Password_txtActionPerformed(evt);
}
});
Connect_Btn.setText("Connect");
Connect_Btn.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Connect_BtnActionPerformed(evt);
}
});
Disconnect_Btn.setText("Disconnect");
Disconnect_Btn.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Disconnect_BtnActionPerformed(evt);
}
});
Chat_LogC.setColumns(20);
Chat_LogC.setRows(5);
jScrollPane1.setViewportView(Chat_LogC);
Send_Btn.setText("Send");
Send_Btn.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Send_BtnActionPerformed(evt);
}
});
localhost_lbl.setText("localhost");
port_no_lbl.setText("1183");
port_no_lbl.setToolTipText("");
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(Address_lbl, javax.swing.GroupLayout.PREFERRED_SIZE, 62, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(localhost_lbl))
.addGroup(layout.createSequentialGroup()
.addComponent(Username_lbl, javax.swing.GroupLayout.PREFERRED_SIZE, 62, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(Username_txt, javax.swing.GroupLayout.PREFERRED_SIZE, 89, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(24, 24, 24)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(Port_Number_lbl)
.addComponent(Password_lbl))
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(Password_txt, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(port_no_lbl))
.addGap(25, 25, 25)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(Disconnect_Btn, javax.swing.GroupLayout.DEFAULT_SIZE, 107, Short.MAX_VALUE)
.addComponent(Connect_Btn, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(layout.createSequentialGroup()
.addComponent(dialogue_txt, javax.swing.GroupLayout.PREFERRED_SIZE, 338, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(Send_Btn, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(Address_lbl)
.addComponent(localhost_lbl))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(Port_Number_lbl)
.addComponent(port_no_lbl))
.addComponent(Connect_Btn))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(Username_lbl)
.addComponent(Username_txt, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(Password_lbl)
.addComponent(Password_txt, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(Disconnect_Btn))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 257, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(dialogue_txt)
.addComponent(Send_Btn, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
getAccessibleContext().setAccessibleName("Client_Frame");
pack();
}// </editor-fold>
private void Username_txtActionPerformed(java.awt.event.ActionEvent evt) {
}
/**
* Button that opens the communication channel to the server that client
* is connecting to, then prepare input/output streams for sending or
* receiving of data to message if the communication was a success.
* @param
*/
private void Connect_BtnActionPerformed(java.awt.event.ActionEvent evt) {
String empty = "";
if (((Username_txt.getText()).equals(empty)) && isConnected == false) {
Chat_LogC.append("No Username entry was found? \n");
} else if (isConnected == false) {
username = Username_txt.getText();
Username_txt.setEditable(false);
Password_txt.setEditable(false);
try {
Connection_Socket = new Socket(address, port_no);
InputStreamReader inpRd = new InputStreamReader(Connection_Socket.getInputStream());
in_From_User = new BufferedReader(inpRd);
out_To_Server = new PrintWriter(Connection_Socket.getOutputStream());
out_To_Server.println(username + ":has connected:Connect");
out_To_Server.flush();
isConnected = true;
} catch (Exception ex) {
Chat_LogC.append("Connection unsuccessful \n");
Username_txt.setEditable(true);
Password_txt.setEditable(true);
}
ListenThread();
} else if (isConnected == true) {
Chat_LogC.append("You're already connected \n");
}
}
/**
* As soon as user disconnect from chat room, their chat log is cleared
*/
private void Disconnect_BtnActionPerformed(java.awt.event.ActionEvent evt) {
if (isConnected == true) {
Chat_LogC.setText("");
Req_Disconnect();
Disconnect();
} else {
Chat_LogC.append("You're already disconnected \n");
}
}
/**
* Sends a message to the server, with specifics of which client the
* message comes from and enclosed in try-catch block for unexpected
* exceptions.
* @param
*/
private void Send_BtnActionPerformed(java.awt.event.ActionEvent evt) {
String nothing = "";
if ((dialogue_txt.getText()).equals(nothing)) {
dialogue_txt.setText("");
dialogue_txt.requestFocus();
} else {
try {
out_To_Server.println(username + ":" + dialogue_txt.getText() + ":" + "Chat");
out_To_Server.flush(); // flushes the buffer
} catch (Exception ex) {
Chat_LogC.append("Message failed to send \n");
}
dialogue_txt.setText("");
dialogue_txt.requestFocus();
}
dialogue_txt.setText("");
dialogue_txt.requestFocus();
}
private void Password_txtActionPerformed(java.awt.event.ActionEvent evt) {
}
/* Main method of the client frame to execute its JFrame */
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new TCP_Client().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JLabel Address_lbl;
private javax.swing.JTextArea Chat_LogC;
private javax.swing.JButton Connect_Btn;
private javax.swing.JButton Disconnect_Btn;
private javax.swing.JLabel Password_lbl;
private javax.swing.JTextField Password_txt;
private javax.swing.JLabel Port_Number_lbl;
private javax.swing.JButton Send_Btn;
private javax.swing.JLabel Username_lbl;
private javax.swing.JTextField Username_txt;
private javax.swing.JTextField dialogue_txt;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JLabel localhost_lbl;
private javax.swing.JLabel port_no_lbl;
// End of variables declaration
}