所以我试图做的是带有客户端的服务器。服务器启动服务器的位置,客户端打开聊天室,在那里他可以写任何他想要的东西。
所以我有两个问题,我无法让它发挥作用。
我希望它如何
是的。我会尽力帮助让它按照我的意愿运作。
问候
Thrillofit
CODE
ServerGUI
package Server;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
/*
* The server as a GUI
*/
public class ServerGUI extends JFrame implements ActionListener, WindowListener {
private static final long serialVersionUID = 1L;
// the stop and start buttons
private JButton stopStart, saveLog;
// JTextArea for the chat room and the events
private JTextArea chat;
// private JTextArea event;
// The port number
private JTextField tfPortNumber;
// my server
private Server server;
// server constructor that receive the port to listen to for connection as
// parameter
ServerGUI(int port) {
super("Chat Server");
server = null;
// in the NorthPanel the PortNumber the Start and Stop buttons
JPanel north = new JPanel();
north.add(new JLabel("Port number: "));
tfPortNumber = new JTextField("" + port);
north.add(tfPortNumber);
// to stop or start the server, we start with "Start"
stopStart = new JButton("Start");
stopStart.addActionListener(this);
saveLog = new JButton("Save log");
saveLog.addActionListener(this);
north.add(stopStart);
north.add(saveLog);
add(north, BorderLayout.NORTH);
// the event and chat room
JPanel center = new JPanel(new GridLayout());
chat = new JTextArea(120, 20);
chat.setEditable(false);
chat.setWrapStyleWord(true);
chat.setLineWrap(true);
appendRoom(null, "Chat room and Events log for server.\n");
center.add(new JScrollPane(chat));
// event = new JTextArea(80,80);
// event.setEditable(false);
// appendEvent("Events log.\n");
// center.add(new JScrollPane(event));
add(center);
// need to be informed when the user click the close button on the frame
addWindowListener(this);
setSize(450, 600);
setVisible(true);
}
public void writeLog() throws IOException {
String saveText = chat.getText();
JFileChooser chooser = new JFileChooser();
// chooser.setCurrentDirectory(new File("./"));
int actionDialog = chooser.showSaveDialog(this);
if (actionDialog == JFileChooser.APPROVE_OPTION) {
File fileName = new File(chooser.getSelectedFile() + "");
if (fileName == null)
return;
if (fileName.exists()) {
actionDialog = JOptionPane.showConfirmDialog(this,
"Replace existing file?");
if (actionDialog == JOptionPane.NO_OPTION)
return;
}
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(fileName), "ISO-8859-1"))) {
bw.write(saveText);
// bw.newLine();
bw.flush();
}
}
}
// append message to the two JTextArea
// position at the end
void appendRoom(String chatStr, String eventStr) {
chat.append(chatStr);
chat.append(eventStr);
// chat.setCaretPosition(chat.getText().length() - 1);
}
// void appendEvent(String str) {
// event.append(str);
// event.setCaretPosition(chat.getText().length() - 1);
//
// }
// start or stop where clicked
public void actionPerformed(ActionEvent e) {
// if running we have to stop
if (e.getSource() == saveLog) {
try {
writeLog();
} catch (IOException e1) {
e1.printStackTrace();
}
} else if (e.getSource() == stopStart) {
if (server != null) {
server.stop();
server = null;
tfPortNumber.setEditable(true);
stopStart.setText("Start");
return;
}
// OK start the server
int port;
try {
port = Integer.parseInt(tfPortNumber.getText().trim());
} catch (Exception er) {
appendRoom(null, "Invalid port number");
return;
}
// ceate a new Server
server = new Server(port, this);
// and start it as a thread
new ServerRunning().start();
stopStart.setText("Stop");
tfPortNumber.setEditable(false);
}
}
/*
* A thread to run the Server
*/
class ServerRunning extends Thread {
public void run() {
server.start(); // should execute until if fails
// the server failed
stopStart.setText("Start");
tfPortNumber.setEditable(true);
appendRoom(null, "Server closed\n");
server = null;
}
}
// entry point to start the Server
public static void main(String[] arg) {
// start server default port 1500
new ServerGUI(1500);
}
/*
* If the user click the X button to close the application I need to close
* the connection with the server to free the port
*/
public void windowClosing(WindowEvent e) {
// if my Server exist
if (server != null) {
try {
server.stop(); // ask the server to close the conection
} catch (Exception eClose) {
}
server = null;
}
// dispose the frame
dispose();
System.exit(0);
}
// I can ignore the other WindowListener method
public void windowClosed(WindowEvent e) {
}
public void windowOpened(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
public void windowDeiconified(WindowEvent e) {
}
public void windowActivated(WindowEvent e) {
}
public void windowDeactivated(WindowEvent e) {
}
// /*
// * A thread to run the Server
// */
// class ServerRunning extends Thread {
// public void run() {
// server.start(); // should execute until if fails
// // the server failed
// stopStart.setText("Start");
// tfPortNumber.setEditable(true);
// appendRoom(null, "Server closed\n");
// server = null;
// }
// }
}
我认为它是唯一需要此代码的代码。如果没有,请告诉我。
更新1:
ClientGUI.java
package Server;
import javax.swing.*;
/*
* The Client with its GUI
*/
public class ClientGUI extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private JLabel lblusername;
private JTextField textfieldusername, textfieldserver, textfieldportnumber;
private JButton btnlogin, btnlogout, btnonline;
private JTextArea textareamessage;
private boolean connected;
private Client client;
private int defaultPort;
private String defaultHost;
ClientGUI(String host, int port) {
super("Chat Client");
defaultPort = port;
defaultHost = host;
JPanel northPanel = new JPanel(new GridLayout(2,2));
JPanel serverAndPort = new JPanel(new GridLayout(1,2, 2, 2));
JLabel lblserveraddress = new JLabel("Server Address: ");
JLabel lblchat = new JLabel(" #BallIsLife");
JLabel lblportnumber = new JLabel("Port Number: ");
textfieldserver = new JTextField(host);
textfieldserver.setHorizontalAlignment(SwingConstants.LEFT);
textfieldserver.setFont(new Font("Tahoma", Font.PLAIN, 20));
textfieldportnumber = new JTextField("" + port);
textfieldportnumber.setFont(new Font("Tahoma", Font.PLAIN, 20));
textfieldportnumber.setHorizontalAlignment(SwingConstants.LEFT);
lblserveraddress.setFont(new Font("Tahoma", Font.PLAIN, 19));
serverAndPort.add(lblserveraddress);
serverAndPort.add(textfieldserver);
serverAndPort.add(lblchat);
serverAndPort.add(lblportnumber);
serverAndPort.add(textfieldportnumber);
lblchat.setForeground(Color.RED);
lblportnumber.setFont(new Font("Tahoma", Font.PLAIN, 19));
northPanel.add(serverAndPort);
getContentPane().add(northPanel, BorderLayout.NORTH);
JPanel panelbtn = new JPanel();
northPanel.add(panelbtn);
btnlogin = new JButton("Login");
panelbtn.add(btnlogin);
btnlogin.setFont(new Font("Tahoma", Font.PLAIN, 17));
btnlogin.addActionListener(this);
btnonline = new JButton("Online");
panelbtn.add(btnonline);
btnonline.setFont(new Font("Tahoma", Font.PLAIN, 17));
btnonline.addActionListener(this);
btnonline.setEnabled(false);
btnlogout = new JButton("Logout");
panelbtn.add(btnlogout);
btnlogout.setFont(new Font("Tahoma", Font.PLAIN, 17));
btnlogout.addActionListener(this);
btnlogout.setEnabled(false);
JButton btnPicture = new JButton("Picture");
btnPicture.setFont(new Font("Tahoma", Font.PLAIN, 17));
btnPicture.setEnabled(false);
panelbtn.add(btnPicture);
textareamessage = new JTextArea("Welcome to the #BallIsLife Chat room.\n");
textareamessage.setFont(new Font("Monospaced", Font.PLAIN, 15));
textareamessage.setLineWrap(true);
textareamessage.setEditable(false);
JPanel centerPanel = new JPanel(new GridLayout(1,1));
JScrollPane scrollPane = new JScrollPane(textareamessage);
centerPanel.add(scrollPane);
getContentPane().add(centerPanel, BorderLayout.CENTER);
JPanel southPanel = new JPanel();
getContentPane().add(southPanel, BorderLayout.SOUTH);
lblusername = new JLabel("Enter your username", SwingConstants.CENTER);
lblusername.setFont(new Font("Tahoma", Font.PLAIN, 15));
southPanel.add(lblusername);
textfieldusername = new JTextField("Write your username here.");
textfieldusername.setFont(new Font("Tahoma", Font.PLAIN, 14));
textfieldusername.setColumns(50);
southPanel.add(textfieldusername);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(823, 665);
setVisible(true);
}
//Logiken
void append(String str) {
textareamessage.append(str);
textareamessage.setCaretPosition(textareamessage.getText().length() - 1);
}
void connectionFailed() {
btnlogin.setEnabled(true);
btnlogout.setEnabled(false);
btnonline.setEnabled(false);
lblusername.setText("Enter your username");
textfieldusername.setText("Write your username here");
textfieldportnumber.setText("" + defaultPort);
textfieldserver.setText(defaultHost);
textfieldserver.setEditable(false);
textfieldportnumber.setEditable(false);
textfieldusername.removeActionListener(this);
connected = false;
}
//
public void actionPerformed(ActionEvent e) {
Object button = e.getSource();
if(button == btnlogout) {
client.sendMessage(new ChatMessage(ChatMessage.LOGOUT, "")); //Ändra till Chatmessage klass
btnlogin.setText("Login");
return;
}
if(button == btnonline) {
client.sendMessage(new ChatMessage(ChatMessage.WHOISIN, "")); //Ändra till Chatmessage klass
return;
}
if(connected) {
client.sendMessage(new ChatMessage(ChatMessage.MESSAGE, textfieldusername.getText())); //Ändra till Chatmessage klass
textfieldusername.setText("");
return;
}
if(button == btnlogin) {
String username = textfieldusername.getText();
if(username.length() == 0)
return;
String server = textfieldserver.getText();
if(server.length() == 0)
return;
String portNumber = textfieldportnumber.getText();
if(portNumber.length() == 0)
return;
int port = 0;
try {
port = Integer.parseInt(portNumber);
}
catch(Exception en) {
return;
}
client = new Client(server, port, username, this);
if(!client.start())
return;
}
connected = true;
textfieldusername.setText("");
btnlogin.setText("Send message");
btnlogin.setEnabled(true);
btnlogout.setEnabled(true);
btnonline.setEnabled(true);
textfieldserver.setEditable(false);
textfieldportnumber.setEditable(false);
textfieldusername.addActionListener(this);
}
// to start the whole thing the server
public static void main(String[] args) {
new ClientGUI("localhost", 1500);
}
}
Server.java
package Server;
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.*;
/*
* The server that can be run both as a console application or a GUI
*/
public class Server {
// a unique ID for each connection
private static int uniqueId;
// an ArrayList to keep the list of the Client
private ArrayList<ClientThread> al;
// if I am in a GUI
private ServerGUI sg;
// to display time
private SimpleDateFormat sdf;
// the port number to listen for connection
private int port;
// the boolean that will be turned of to stop the server
private boolean keepGoing;
/*
* server constructor that receive the port to listen to for connection as parameter
* in console
*/
public Server(int port) {
this(port, null);
}
public Server(int port, ServerGUI sg) {
// GUI or not
this.sg = sg;
// the port
this.port = port;
// to display hh:mm:ss
sdf = new SimpleDateFormat("HH:mm:ss");
// ArrayList for the Client list
al = new ArrayList<ClientThread>();
}
public void start() {
keepGoing = true;
/* create socket server and wait for connection requests */
try
{
// the socket used by the server
ServerSocket serverSocket = new ServerSocket(port);
// infinite loop to wait for connections
while(keepGoing)
{
// format message saying we are waiting
display("Server waiting for Clients on port " + port + ".");
Socket socket = serverSocket.accept(); // accept connection
// if I was asked to stop
if(!keepGoing)
break;
ClientThread t = new ClientThread(socket); // make a thread of it
al.add(t); // save it in the ArrayList
t.start();
}
// I was asked to stop
try {
serverSocket.close();
for(int i = 0; i < al.size(); ++i) {
ClientThread tc = al.get(i);
try {
tc.sInput.close();
tc.sOutput.close();
tc.socket.close();
}
catch(IOException ioE) {
// not much I can do
}
}
}
catch(Exception e) {
display("Exception closing the server and clients: " + e);
}
}
// something went bad
catch (IOException e) {
String msg = sdf.format(new Date()) + " Exception on new ServerSocket: " + e + "\n";
display(msg);
}
}
/*
* For the GUI to stop the server
*/
protected void stop() {
keepGoing = false;
// connect to myself as Client to exit statement
// Socket socket = serverSocket.accept();
try {
new Socket("localhost", port);
}
catch(Exception e) {
// nothing I can really do
}
}
/*
* Display an event (not a message) to the console or the GUI
*/
private void display(String msg) {
String time = sdf.format(new Date()) + " " + msg;
if(sg == null)
System.out.println(time);
else
sg.appendRoom(null,time + "\n");
}
/*
* to broadcast a message to all Clients
*/
private synchronized void broadcast(String message) {
// add HH:mm:ss and \n to the message
String time = sdf.format(new Date());
String messageLf = time + " " + message + "\n";
// display message on console or GUI
if(sg == null)
System.out.print(messageLf);
else
sg.appendRoom(messageLf,null); // append in the room window
// we loop in reverse order in case we would have to remove a Client
// because it has disconnected
for(int i = al.size(); --i >= 0;) {
ClientThread ct = al.get(i);
// try to write to the Client if it fails remove it from the list
if(!ct.writeMsg(messageLf)) {
al.remove(i);
display("Disconnected Client " + ct.username + " removed from list.");
}
}
}
// for a client who logoff using the LOGOUT message
synchronized void remove(int id) {
// scan the array list until we found the Id
for(int i = 0; i < al.size(); ++i) {
ClientThread ct = al.get(i);
// found it
if(ct.id == id) {
al.remove(i);
return;
}
}
}
/*
* To run as a console application just open a console window and:
* > java Server
* > java Server portNumber
* If the port number is not specified 1500 is used
*/
public static void main(String[] args) {
// start server on port 1500 unless a PortNumber is specified
int portNumber = 1500;
switch(args.length) {
case 1:
try {
portNumber = Integer.parseInt(args[0]);
}
catch(Exception e) {
System.out.println("Invalid port number.");
System.out.println("Usage is: > java Server [portNumber]");
return;
}
case 0:
break;
default:
System.out.println("Usage is: > java Server [portNumber]");
return;
}
// create a server object and start it
Server server = new Server(portNumber);
server.start();
}
/** One instance of this thread will run for each client */
class ClientThread extends Thread {
// the socket where to listen/talk
Socket socket;
ObjectInputStream sInput;
ObjectOutputStream sOutput;
// my unique id (easier for deconnection)
int id;
// the Username of the Client
String username;
// the only type of message a will receive
ChatMessage cm;
// the date I connect
String date;
// Constructore
ClientThread(Socket socket) {
// a unique id
id = ++uniqueId;
this.socket = socket;
/* Creating both Data Stream */
System.out.println("Thread trying to create Object Input/Output Streams");
try
{
// create output first
sOutput = new ObjectOutputStream(socket.getOutputStream());
sInput = new ObjectInputStream(socket.getInputStream());
// read the username
username = (String) sInput.readObject();
display(username + " just connected.");
}
catch (IOException e) {
display("Exception creating new Input/output Streams: " + e);
return;
}
// have to catch ClassNotFoundException
// but I read a String, I am sure it will work
catch (ClassNotFoundException e) {
}
date = new Date().toString() + "\n";
}
// what will run forever
public void run() {
// to loop until LOGOUT
boolean keepGoing = true;
while(keepGoing) {
// read a String (which is an object)
try {
cm = (ChatMessage) sInput.readObject();
}
catch (IOException e) {
display(username + " Exception reading Streams: " + e);
break;
}
catch(ClassNotFoundException e2) {
break;
}
// the messaage part of the ChatMessage
String message = cm.getMessage();
// Switch on the type of message receive
switch(cm.getType()) {
case ChatMessage.MESSAGE:
broadcast(username + ": " + message);
break;
case ChatMessage.LOGOUT:
display(username + " disconnected with a LOGOUT message.");
keepGoing = false;
break;
case ChatMessage.WHOISIN:
writeMsg("List of the users connected at " + sdf.format(new Date()) + "\n");
// scan al the users connected
for(int i = 0; i < al.size(); ++i) {
ClientThread ct = al.get(i);
writeMsg((i+1) + ") " + ct.username + " since " + ct.date);
}
break;
}
}
// remove myself from the arrayList containing the list of the
// connected Clients
remove(id);
close();
}
// try to close everything
private void close() {
// try to close the connection
try {
if(sOutput != null) sOutput.close();
}
catch(Exception e) {}
try {
if(sInput != null) sInput.close();
}
catch(Exception e) {};
try {
if(socket != null) socket.close();
}
catch (Exception e) {}
}
/*
* Write a String to the Client output stream
*/
private boolean writeMsg(String msg) {
// if Client is still connected send the message to it
if(!socket.isConnected()) {
close();
return false;
}
// write the message to the stream
try {
sOutput.writeObject(msg);
}
// if an error occurs, do not abort just inform the user
catch(IOException e) {
display("Error sending message to " + username);
display(e.toString());
}
return true;
}
}
}
答案 0 :(得分:2)
添加成员变量chatContent并编写如下方法以向其中添加内容。
StringBuilder chatContent = new StringBuilder();
private void addText(String chatText){
chatContent.append(chatText).append("\n");
}
并在每次附加到聊天文本区域时调用它,并且在写入文件时使用此chatContent作为要写入的内容源。
也许会有所帮助。
或者您也可以使用
将内容直接流式传输到文件中FileOutputStream
更新1:
选中此JTextArea txt; txt.getText() skips "\n"
这可能会有所帮助。
更新2
// Replace this line
File fileName = new File(chooser.getSelectedFile() + "");
// With following code
String _fileName = chooser.getSelectedFile();
if(_fileName != null && !_fileName.endsWith(".txt")){
_fileName = _fileName + ".txt";
}
File fileName = new File(_fileName);