When I send a message to the server, it retrieves it 100% of the time, but my client only displays every other message. It really makes no sense to me.. I used to use JTextAreas, but I decided to switch to JTextPanes, and yeah, not going so well.
In my ClientFrame.java, I have displayMessage(String message)
, which is being called in my Client's run()
. Since I've had problems before with not posting enough of my code, I'ma post EVERYTHING i have.. Main classes used are ClientFrame, Client, Server (for the sendGlobalMesssage(String message)
, and User for my server-thread.
Client.java
import java.io.IOException;
import javax.swing.text.BadLocationException;
public class Client extends Stream implements Runnable {
public boolean running = false;
private Thread clientThread;
ClientFrame frame;
public Client() {
super("localhost", 43594);
frame = new ClientFrame(500, 500);
start();
}
public synchronized void start() {
if(running) return;
running = true;
clientThread = new Thread(this);
clientThread.start();
}
public synchronized void stop() {
if(!running) return;
running = false;
clientThread.interrupt();
try {
clientThread.join();
} catch (InterruptedException e) {e.printStackTrace();}
}
public static void sendMessage(String message) {
try{
out.writeObject(message);
out.flush();
}catch(IOException e) { }
}
public void run() {
try{
setupStream();
while(running) {
if(recieveData() != null) {
frame.displayMessage(recieveData());
}
}
}catch(IOException | BadLocationException | ClassNotFoundException e) {
e.printStackTrace();
}finally {
try{
out.close();
in.close();
socket.close();
clientThread.join();
}catch(IOException | InterruptedException e) { e.printStackTrace(); }
}
}
public static void main(String[] args) {
new Client();
}
}
Client's Stream.java
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class Stream {
Socket socket;
static ObjectOutputStream out;
static ObjectInputStream in;
String data;
public Stream(String host, int port) {
try {
socket = new Socket(host, port);
} catch (IOException e) {
e.printStackTrace();
}
}
protected void setupStream() throws IOException {
out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
in = new ObjectInputStream(socket.getInputStream());
}
public synchronized String recieveData() throws IOException, ClassNotFoundException {
return (String) in.readObject();
}
}
ClientFrame.java
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class ClientFrame extends Frame {
private JPanel mainpanel;
public ClientFrame(int width, int height) {
super(width, height);
mainpanel = new JPanel();
addContentToPanel();
setListeners();
add(mainpanel);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
private void addContentToPanel() {
mainpanel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
setGbc(0, 0, width, height-460, gbc);
mainpanel.add(topPanel(), gbc);
setGbc(0, 1, 0, 0, gbc);
mainpanel.add(chatPanel(), gbc);
}
JTextField userfield;
JPasswordField passfield;
JPanel topPanel() {
JPanel panel = new JPanel();
panel.setLayout(null);
JLabel label = new JLabel("Username: ");
label.setBounds(15, 1, 65, 30);
userfield = new JTextField();
userfield.setBounds(85, 7, 160, 20);
panel.add(label);
panel.add(userfield);
label = new JLabel("Password: ");
label.setBounds(255, 1, 65, 30);
passfield = new JPasswordField();
passfield.setBounds(325, 7, 160, 20);
panel.add(label);
panel.add(passfield);
return panel;
}
JTextPane toptextpane;
JTextPane bottomtextpane;
JScrollPane topscrollpane;
JScrollPane bottomscrollpane;
JPanel chatPanel() {
JPanel chatpanel = new JPanel();
chatpanel.setPreferredSize(new Dimension(width, height - 40));
chatpanel.setLayout(null);
toptextpane = new JTextPane();
toptextpane.setEditable(false);
topscrollpane = new JScrollPane(toptextpane);
topscrollpane.setBounds(5, 0, width - 10, height - 200);
chatpanel.add(topscrollpane);
bottomtextpane = new JTextPane();
bottomscrollpane = new JScrollPane(bottomtextpane);
bottomscrollpane.setBounds(5, 305, width - 10, height - 350);
chatpanel.add(bottomscrollpane);
return chatpanel;
}
Document doc;
public void displayMessage(String message) throws BadLocationException {
Document doc = toptextpane.getDocument();
try
{
System.out.println("works");
doc.insertString(0, message +"\n", null );
}
catch(Exception e) { System.out.println(e); }
}
private void setListeners() {
bottomtextpane.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER) {
Client.sendMessage(bottomtextpane.getText());
bottomtextpane.setText("");
e.consume();
}
}
});
}
}
Server.java
package Server;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
public class Server {
public static int maxConnections = 10;
private ServerSocket serverSocket;
static User[] user = new User[maxConnections];
public static void sendGlobalMessage(String message) {
for(int i = 0; i < 9; i++) {
if(user[i] != null) {
try {
user[i].out.writeObject(message);
user[i].out.flush();
System.out.println(message);
}catch(IOException e) { }
}
}
}
public static HashMap<String, User> users = new HashMap<String, User>();
Thread acceptConnections = new Thread(new Runnable() {
public void run() {
while(User.users <= maxConnections) {
try{
System.out.println("[System] Waiting for connections.. ("+User.users+" users online)");
for(int i = 0; i < 9; i++) {
if(user[i] == null) {
user[i] = new User(serverSocket.accept());
user[i].ID = i;
System.out.println("--- Someone has joined! ---");
user[i].start();
User.users++;
break ;
}
}
}catch(IOException e) { }
}
}
});
Thread scannerThread;
Scanner scanner;
public Server() {
scannerThread = new Thread(new Runnable() {
public void run() {
scanner = new Scanner(System.in);
String input;
while((input = scanner.nextLine()) != null) {
switch(input.toLowerCase()) {
case "checkuser":
}
}
}
});
try{
scannerThread.start();
serverSocket = new ServerSocket(43594);
}catch(IOException e) { }
}
public static void main(String args[]) throws Exception {
Server server = new Server();
server.acceptConnections.start();
}
}
User.java
package Server;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
public class User extends Thread {
public static int users = 0;
public int ID;
public String username;
boolean online = false;
public static ArrayList<String> usernames = new ArrayList<String>();
Socket socket;
ObjectOutputStream out;
ObjectInputStream in;
String input;
public User(Socket socket) {
this.socket = socket;
}
public String decode(String input) {
String[] split = input.split(" ");
if(input.startsWith("::")) {
try {
switch(split[0].substring(2, split[0].length()).toLowerCase()) {
case "setname":
case "changename":
case "newname":
if(usernames.contains(split[1].toLowerCase())) {
out.writeUTF("This name is already taken! Please choose a different one.");
out.flush();
return null;
}
if(username == null) {
username = split[1].substring(0, 1).toUpperCase() + split[1].substring(1, split[1].length());
Server.users.put(split[1].toLowerCase(), Server.user[ID]);
usernames.add(split[1].toLowerCase());
} else {
usernames.remove(username.toLowerCase());
username = split[1].substring(0, 1).toUpperCase() + split[1].substring(1, split[1].length());
usernames.add(split[1].toLowerCase());
}
return null;
case "rank+":
return null;
case "[sm]=":
return null;
}
}catch(IOException e) { }
}
return input;
}
String timeStamp;
public void run() {
try {
out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
in = new ObjectInputStream(socket.getInputStream());
while((input = (String) in.readObject()) != null) {
input = decode(input);
if(input != null) {
if(username != null) {
timeStamp = new SimpleDateFormat("[h:mm:ss] ").format(Calendar.getInstance().getTime());
Server.sendGlobalMessage(timeStamp + username +": "+input);
} else {
timeStamp = new SimpleDateFormat("[h:mm:ss] ").format(Calendar.getInstance().getTime());
Server.sendGlobalMessage(timeStamp + "Guest "+ID+": "+input);
}
}
}
}catch(IOException | ClassNotFoundException e) { try{
out.close();
in.close();
socket.close();
} catch(IOException e2) { e.printStackTrace(); } } finally {
}
}
}
Also, something that would be MUCH appreciated (if you can), show me a more proper way to close my streams, both server AND client-sided. Thanks :)