I am creating a multiclient chat server program. Messages are sent as Message objects. The ServerClient class is not recieving the messages, though, and I don't know why.
Client:
package client;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.*;
import constraints.Constraints;
import message.Message;
import tools.Tools;
import window.ApplicationWindow;
#SuppressWarnings("serial")
public class Client extends ApplicationWindow {
private static final int portNumber = 4444;
private boolean send = false;
private String userName;
private String serverHost;
private int serverPort;
private GridBagLayout layout;
private JTextArea textArea;
private Constraints c_textArea;
private JTextField textField;
private Constraints c_textField;
public static void main(String[] args){
String readName = System.getProperty("user.name");
Client client = new Client(readName, portNumber);
client.startClient();
}
private Client(String userName, int portNumber){
super("ChatApp");
Tools.setLookAndFeel();
this.userName = userName;
this.serverPort = portNumber;
try {
this.serverHost = InetAddress.getLocalHost().getHostAddress();
}catch(Exception e) {
}
layout = new GridBagLayout();
setLayout(layout);
textArea = new JTextArea();
textArea.setColumns(75);
textArea.setRows(20);
c_textArea = new Constraints(0,1);
textArea.setLineWrap(true);
textArea.setEditable(false);
textArea.setVisible(true);
JScrollPane scroll = new JScrollPane (textArea);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
add(scroll, c_textArea);
textField = new JTextField();
textField.setColumns(50);
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
send = true;
}
});
c_textField = new Constraints(0,2);
add(textField, c_textField);
pack();
setVisible(true);
setResizable(false);
}
public void output(String message) {
this.textArea.setText(this.textArea.getText() + "\n" + message);
}
private void startClient() {
try{
Socket socket = new Socket(serverHost, serverPort);
Thread.sleep(1000);
ServerThread serverThread = new ServerThread(socket, userName, this);
Thread serverAccessThread = new Thread(serverThread);
serverAccessThread.start();
while(serverAccessThread.isAlive() && this.isRunning()) {
if (send) {
Message message = new Message(textField.getText(), "[" + "]", this.userName);
serverThread.addNextMessage(message);
send = false;
textField.setText("");
}
Thread.sleep(200);
}
}catch(IOException ex){
output("Could not connect to server!");
}catch(InterruptedException ex){
output("Connection interrupted!");
}
}
public void setHost(String serverHost) {
this.serverHost = serverHost;
}
}
ServerClient:
package server;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketException;
import java.util.Scanner;
import message.Message;
public class ServerClient implements Runnable {
private Socket socket;
private PrintWriter clientOut;
private ChatServer server;
private boolean running;
public ServerClient(ChatServer server, Socket socket) {
this.server = server;
this.socket = socket;
this.running = true;
}
private PrintWriter getWriter(){
return clientOut;
}
public boolean isRunning() {
return this.running;
}
public void stop() {
this.running = false;
}
#Override
public void run() {
try{
this.clientOut = new PrintWriter(socket.getOutputStream(), false);
clientOut.flush();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
while(!socket.isClosed()){
try {
if (in.available() > 0) {
Object i = in.readObject();
if (!i.equals(null)) {
Message input = (Message) i;
String message = input.getText();
String time = input.getTimestamp();
String user = input.getUser();
for(ServerClient thatClient : server.getClients()){
PrintWriter thatClientOut = thatClient.getWriter();
if(thatClientOut != null){
thatClientOut.write(time + " " + user + ": " + message + "\r\n");
thatClientOut.flush();
}
}
}
}
} catch (ClassNotFoundException e) {
System.out.println(e);
} catch (SocketException ex) {
System.out.println(ex);
break;
}
}
in.close();
this.stop();
} catch (IOException e) {
e.printStackTrace();
}
}
//public void fileWrite()
}
ChatServer:
package server;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
//import javax.swing.JComboBox;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import constraints.Constraints;
import tools.Tools;
import window.ApplicationWindow;
import message.Message;
#SuppressWarnings("serial")
public class ChatServer extends ApplicationWindow {
private static final int portNumber = 4444;
private ArrayList<Command> commands;
private int serverPort;
private String serverHost;
private List<ServerClient> clients;
ServerSocket serverSocket;
private GridBagLayout layout;
private JTextArea textArea;
private Constraints c_textArea;
private JTextField textField;
private Constraints c_textField;
public static void main(String[] args){
ChatServer server = new ChatServer(portNumber);
server.startServer();
}
public ChatServer(int portNumber){
super("Server " + portNumber);
this.serverPort = portNumber;
try {
this.serverHost = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
this.serverHost = "";
}
Tools.setLookAndFeel();
initActions();
layout = new GridBagLayout();
setLayout(layout);
textArea = new JTextArea();
textArea.setColumns(75);
textArea.setRows(20);
c_textArea = new Constraints(0,1);
textArea.setLineWrap(true);
textArea.setEditable(false);
textArea.setVisible(true);
JScrollPane scroll = new JScrollPane (textArea);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
add(scroll, c_textArea);
textField = new JTextField();
textField.setColumns(50);
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
process(textField.getText());
}
});
c_textField = new Constraints(0,2);
add(textField, c_textField);
pack();
setVisible(true);
setResizable(false);
}
public List<ServerClient> getClients(){
return clients;
}
private void startServer(){
clients = new ArrayList<ServerClient>();
serverSocket = null;
try {
InetAddress addr = InetAddress.getByName(this.serverHost);
serverSocket = new ServerSocket(serverPort, 50, addr);
acceptClients(serverSocket);
} catch (IOException e){
output("[ERROR] COULD NOT LISTEN ON PORT: " + serverPort);
this.stop();
}
}
private void acceptClients(ServerSocket serverSocket){
output("[BEGIN] SERVER STARTING ON PORT: " + serverSocket.getLocalSocketAddress());
while (this.isRunning()) {
try{
Socket socket = serverSocket.accept();
output("[ACCEPT] ACCEPTED CLIENT AT: " + socket.getRemoteSocketAddress());
ServerClient client = new ServerClient(this, socket);
Thread thread = new Thread(client);
thread.start();
clients.add(client);
} catch (IOException ex) {
output("[ERROR] ACCEPT FAILED ON: " + serverPort);
}
}
}
private void initActions() {
this.commands = new ArrayList<Command>();
this.commands.add(new Command() {
public void run() {
output("[COMMAND] IP: " + serverSocket.getInetAddress().toString());
}
public String getTrigger() {
return "-ip";
}
});
this.commands.add(new Command() {
public void run() {
for (ServerClient client : clients) {
if (!client.isRunning()) {
clients.remove(client);
}
}
output("[COMMAND] CLIENTS: " + clients.size());
}
public String getTrigger() {
return "-clients";
}
});
}
public boolean process(String command) {
for (Command c : this.commands) {
if (c.getTrigger().equals(command)) {
c.run();
textField.setText("");
return true;
}
}
return false;
}
public void output(String message) {
this.textArea.setText(this.textArea.getText() + "\n" + message);
}
}
ServerThread:
package client;
import java.io.*;
import java.net.Socket;
import java.util.LinkedList;
import java.util.Scanner;
import message.Message;
#SuppressWarnings("unused")
public class ServerThread implements Runnable {
private Socket socket;
private String userName;
private boolean isAlived;
private final LinkedList<Message> messagesToSend;
private boolean hasMessages = false;
private Client client;
public ServerThread(Socket socket, String userName, Client client){
this.socket = socket;
this.userName = userName;
this.client = client;
messagesToSend = new LinkedList<Message>();
}
public void addNextMessage(Message message) {
synchronized (messagesToSend) {
hasMessages = true;
messagesToSend.push(message);
}
}
#Override
public void run(){
print("Welcome :" + userName);
print("Local Port :" + socket.getLocalPort());
print("Server = " + socket.getRemoteSocketAddress() + ":" + socket.getPort());
try {
ObjectOutputStream serverOut = new ObjectOutputStream(socket.getOutputStream());
serverOut.flush();
ObjectInputStream serverIn = new ObjectInputStream(socket.getInputStream());
while(!socket.isClosed()){
if (serverIn.available() > 0) {
try {
if (serverIn.readObject() != null) {
Message input = (Message) serverIn.readObject();
}
} catch (ClassNotFoundException e) {
System.out.println(e);
}
}
if(hasMessages){
Message nextSend;
synchronized(messagesToSend){
nextSend = messagesToSend.pop();
hasMessages = !messagesToSend.isEmpty();
}
serverOut.writeObject(nextSend);
serverOut.flush();
}
}
serverOut.close();
serverIn.close();
} catch(Exception ex){
ex.printStackTrace();
}
}
public void print(String message) {
this.client.output(message);
}
}
I know that the client is able to connect to the server, and both can get messages and successfully call the writeObject() method. However, the message never gets recieved. Can someone help me?
while(!socket.isClosed()){
if (serverIn.available() > 0) {
try {
if (serverIn.readObject() != null) {
Message input = (Message) serverIn.readObject();
}
} catch (ClassNotFoundException e) {
System.out.println(e);
}
}
if(hasMessages){
Message nextSend;
synchronized(messagesToSend){
nextSend = messagesToSend.pop();
hasMessages = !messagesToSend.isEmpty();
}
serverOut.writeObject(nextSend);
serverOut.flush();
}
}
This is all nonsense.
isClosed() returns true when you have closed the socket. Not when the peer disconnects.
Calling available() here and merely spin-looping while it is false is just literally a waste of time.
ObjectInputStream.readObect() only returns null if you send a null.
You are calling it twice, throwing the first object read away, and then trying to read the next object. So you are throwing away every odd-numbered object.
It should be more like this:
for (;;) {
try {
Message input = (Message) serverIn.readObject();
// process input here
} catch (EOFException e) {
break;
} catch (ClassNotFoundException e) {
System.out.println(e);
}
}
if(hasMessages){
Message nextSend;
synchronized(messagesToSend){
nextSend = messagesToSend.pop();
hasMessages = !messagesToSend.isEmpty();
}
serverOut.writeObject(nextSend);
serverOut.flush();
}
}
You should probably split this into a reading thread and a writing thread, as writeObject() and flush() can also block. Same remarks apply to the other place where you are using isClosed(), available(), testing for null, etc.
The hasMessages flag is also not going to work. It will remain false even though a message got added subsequently. It would be better to delete it and just rely on messagesToSend.isEmpty(), inside a synchronized block:
synchronized(messagesToSend){
while (!messagesToSend.isEmpty()){
Message nextSend = messagesToSend.pop();
serverOut.writeObject(nextSend);
}
}
serverOut.flush();
Related
I'm trying to create a server/client for the purpose of chatting. I start the server which waits for a client to connect, the client connects, but it gets stuck waiting for the client to send the username.
Here is the server:
package chat_server;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class Chat_Server {
private ServerSocket ss;
private Socket connection;
private List<ClientT> users;
private static int usersNumber;
public Chat_Server() {
users = new ArrayList<ClientT>();
usersNumber = 1;
try {
ss = new ServerSocket(2016);
} catch (IOException e) {
e.printStackTrace();
System.err.println(3);
}
}
public void acceptRequests() throws IOException {
while (true) {
try {
connection = ss.accept();
ClientT ct = new ClientT(connection);
users.add(ct);
System.out.print("Connected users: ");
for(int i = 0; i < users.size(); i++)
System.out.print(users.get(i) + " ");
System.out.println();
ct.start();
} catch (IOException e) {
System.out.println("Could not accept connection from client: "
+ e);
System.err.println(4);
}
}
}
}
class ClientT extends Thread {
private Socket s;
private BufferedReader in;
private DataOutputStream out;
private String userName = "a";
private String message;
int userNr;
public ClientT(Socket _s) {
this.s = _s;
userNr = usersNumber++;
System.out.println("In client: s = " + s + " userNr = " + userNr);
try {
System.out.println("Creating 'in' and 'out' objects");
out = new DataOutputStream(s.getOutputStream());
in = new BufferedReader(new InputStreamReader(
s.getInputStream()));
System.out.println("Catching username...");
**//--it gets stuck here--**
userName = (String) in.readLine();
System.out.println(userName + " connected...");
} catch (IOException e) {
e.printStackTrace();
System.err.println(1);
}
}
public void run() {
System.out.println("In ClientT run...");
while (true) {
try {
message = in.readLine();
System.out.println("Message: " + message);
System.out.println("Notifying all clients!");
messageNotifyAll(message);
} catch (IOException e) {}
}
}
}
public static void main(String[] args) throws IOException {
Chat_Server cs = new Chat_Server();
System.out.println("Accepting requests...");
cs.acceptRequests();
}
}
And here the the client:
package chatClient;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.*;
#SuppressWarnings("serial")
public class Client extends JFrame {
private JTextArea textArea;
private JScrollPane scrollPane;
private JPanel panelButtons;
private JPanel panelList;
private JButton send;
private JButton disconnect;
#SuppressWarnings("rawtypes")
private JList userList;
private JLabel connectedUsers;
private JTextField text;
private JButton sendMessage;
private String name;
private Socket s;
BufferedReader in;
DataOutputStream out;
#SuppressWarnings("rawtypes")
public Client(String _name) throws InterruptedException {
System.out.println("Loading GUI...");
//GUI left out
System.out.println("Loading GUI finished...");
connectToServer();
}
public void connectToServer() throws InterruptedException {
try {
textArea.append("Connecting to server...\n");
s = new Socket("localhost", 2016);
textArea.append("Connected to " + s.getInetAddress() + ":" + s.getPort() +" as " + name + "...");
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
out = new DataOutputStream(s.getOutputStream());
new waitForMessage().start();
out.writeBytes(name);
} catch (UnknownHostException e) {
textArea.append("Server not running!");
// e.printStackTrace();
} catch (IOException e) {
textArea.append(e + "\n");
try {
disconnectFromServer();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public void disconnectFromServer() throws IOException {
s.close();
System.out.println("Disconnected!");
}
public class FrameExit extends WindowAdapter {
public void windowClosing(WindowEvent e) {
e.getWindow().dispose();
}
}
public class Disconnect implements ActionListener {
public void actionPerformed(ActionEvent e) {
try {
s.close();
System.out.println("Disconnecting...");
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public class Send implements ActionListener {
public void actionPerformed(ActionEvent e) {
try {
System.out.println("Sending message: " + text.getText());
out.writeBytes(text.getText());
text.setText("");
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public class waitForMessage extends Thread {
#Override
public void run() {
System.out.println("Waiting for message!");
while (true) {
try {
String message = in.readLine();
System.out
.println("Message received! Displaying message in GUI!");
textArea.append(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
//I have a login GUI from where I start the Client
}
}
Any help would be appreciated!
Server side seems to expect a line to read, but there is no line break sent from the client side.
Also, consider adding out.flush() after you write, to ensure that the data is actually sent.
out.writeBytes(name + System.getProperty("line.separator"));
out.flush();
Note that you could use a PrintWriter instead, which has println methods to take care of new lines.
See : What is the Difference between PrintWriter and DataOutputStream?
I am trying to a simple client server chat application using Stream sockets and Swing. But it is not working as it should. Apparently the server just waits for connection and does not proceed.
I have three java files, Server.java , Client.java and ChatApp.java
Server.java
package com.htpj.networkingChatApp;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Server extends JFrame {
private static final long serialVersionUID = 1L;
private JTextArea displayArea;
private JTextField messageEnterField;
private ServerSocket server;
private Socket connectionSocket;
private ObjectInputStream input;
private ObjectOutputStream output;
private int counter = 1;
protected void serverGui() {
messageEnterField = new JTextField();
setMessageEnterFieldEditable(false);
messageEnterField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sendDataToClient(e.getActionCommand());
}
});
add(messageEnterField, BorderLayout.SOUTH);
displayArea = new JTextArea();
add(new JScrollPane(displayArea), BorderLayout.CENTER);
displayArea.setEditable(false); // display area is never editable
setSize(500, 500);
setLocationRelativeTo(null);
setTitle("Chat Server");
setVisible(true);
}
protected void runServer() {
try {
server = new ServerSocket(2000, 100);
while (true) {
try {
waitForConnection(); // wait for a connection
getStreams(); // get input and output streams
processConnection(); // process connections
} catch (EOFException e) {
displayMessage("\n server terminated the connection");
} finally {
closeConnection();
++counter;
}
}
} catch (IOException e) {
e.printStackTrace();
}
} // ENDOF method runServer
private void waitForConnection() {
try {
displayMessage("Waiting for Connection\n");
connectionSocket = server.accept();
displayMessage("Connection" + counter + "received from: " + connectionSocket.getInetAddress() + "port: "
+ connectionSocket.getPort());
} catch (IOException e) {
e.printStackTrace();
}
} // ENDOF method waitForConnection
private void getStreams() throws IOException {
output = new ObjectOutputStream(connectionSocket.getOutputStream());
output.flush(); // flush output buffer to send header information
input = new ObjectInputStream(connectionSocket.getInputStream());
displayMessage("\n Got I/O Streams \n");
} // ENDOF getStreams method
private void processConnection() throws IOException {
String message = null;
sendDataToClient("Connection Successful \n");
setMessageEnterFieldEditable(true); // enable server to type message
do {
try {
message = (String) input.readObject();
displayMessage("\n" + message);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} while (!message.equals("CLIENT >> TERMINATE"));
} // ENDOF processConnection method
private void closeConnection() {
displayMessage("\n closing connection \n");
setMessageEnterFieldEditable(false);
try {
output.close();
input.close();
connectionSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
} // ENDOF closeConnection method
private void sendDataToClient(String messageFromServer) {
try {
output.writeObject("SERVER>> " + messageFromServer);
output.flush(); // flush output to client
} catch (IOException e) {
e.printStackTrace();
}
} // ENDOF sendDataToClient method
private void displayMessage(String showMessage) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
displayArea.append(showMessage);
}
});
} // ENDOF method displayMessage
private void setMessageEnterFieldEditable(final boolean isEditable) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
messageEnterField.setEditable(isEditable);
}
});
}
} // ENDOF class server
Client.java
package com.htpj.networkingChatApp;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Client extends JFrame {
private static final long serialVersionUID = 1L;
private JTextField messageEnterField;
private JTextArea displayArea;
private String chatHost;
private Socket clientSocket;
private ObjectInputStream input;
private ObjectOutputStream output;
private String message = "";
public Client(String host) {
this.chatHost = host;
}
protected void clientGui() {
messageEnterField = new JTextField();
setMessageEnterFieldEditable(false);
messageEnterField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
sendDataToServer(e.getActionCommand());
}
});
add(messageEnterField, BorderLayout.SOUTH);
displayArea = new JTextArea();
add(new JScrollPane(displayArea), BorderLayout.CENTER);
displayArea.setEditable(false);
setTitle("Chat Client");
setSize(500, 500);
setLocationRelativeTo(null);
setVisible(true);
} // END OF clientGui method
// connect to the server and process message from server
protected void runClient() throws UnknownHostException, IOException, ClassNotFoundException {
// connect to server, get Streams, process connection
try {
connectToServer();
getStreams();
processConnection();
} catch (EOFException e) {
displayMessage("\n client closed the connection");
} finally {
closeConnection();
}
}
private void connectToServer() throws UnknownHostException, IOException {
displayMessage("Attempting Connection to Server: \n");
clientSocket = new Socket(InetAddress.getByName(chatHost), 2000);
displayMessage(
"Connected to: " + clientSocket.getInetAddress().getHostName() + "on Port : " + clientSocket.getPort());
} // END OF method connectToServer
private void getStreams() throws IOException {
output = new ObjectOutputStream(clientSocket.getOutputStream());
output.flush();
input = new ObjectInputStream(clientSocket.getInputStream());
displayMessage("\n Got I/O stream \n ");
} // END OF getStreams method
private void processConnection() throws ClassNotFoundException, IOException {
displayMessage("\n connected to server\n");
setMessageEnterFieldEditable(true);
do {
message = (String) input.readObject();
displayMessage("\n" + message);
} while (!message.equals("SERVER>> TERMINATE"));
} // end of processConnection method
private void closeConnection() throws IOException {
displayMessage("\n closing connection ");
input.close();
output.close();
clientSocket.close();
setMessageEnterFieldEditable(false);
} // end of closeConnection method
private void displayMessage(final String messageToShow) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
displayArea.append(messageToShow);
}
});
} // end of displayMessage method
private void sendDataToServer(String messageToServer) {
try {
output.writeObject(messageToServer);
output.flush();
} catch (IOException e) {
e.printStackTrace();
}
} // end of sendDataToServer method
private void setMessageEnterFieldEditable(final boolean isEditable) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
messageEnterField.setEditable(isEditable);
}
});
}
}
ChatApp.java
package com.htpj.networkingChatApp;
import java.io.IOException;
public class ChatApp{
public static void main(String[] args) {
Server chatServer = new Server();
Client chatClient = new Client("127.0.0.1");
chatServer.serverGui();
chatClient.clientGui();
chatServer.runServer();
try {
chatClient.runClient();
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
}
}
I have a multi-thread chatroom that connects to one server. They all connect, login, and message independently of each other just fine, but when I log off with one of the clients (and the server does a socket.close() for that instance of the client) all clients are logged off. I looked at a bunch of other questions on stackoverflow before posting this, but none of them had the same issue as mine (that I found). Note: All the clients were running locally on my computer, 2+ of them, and that's how I encountered the bug. Could them being on the same IP (though everything is done on my localhost..) cause this to happen? Any help or insight as to what is causing this issue and how I could resolve it would be great. When the issue occurs it also outputs this to the console:
Socket: Socket[addr=localhost/127.0.0.1,port=4000,localport=55650]
Here is the code (how to recreate the bug is at the bottom):
Server class:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;
public class ChatServer {
private static final int PORT = 4000;
private static HashSet<String> names = new HashSet<String>();
private static HashSet<ObjectOutputStream> outputs =
new HashSet<ObjectOutputStream>();
public static void main(String[] args) throws IOException{
System.out.println("The chat server is running...");
ServerSocket listener = new ServerSocket(PORT);
while(true){
new Handler(listener.accept()).start();
}
}
private static class Handler extends Thread{
private String name;
private Socket socket;
private ObjectInputStream in;
private ObjectOutputStream out;
private boolean loggedOut;
public Handler(Socket socket){
this.socket = socket;
}
public void run(){
try {
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
loggedOut = false;
while(true){
Message message = (Message) in.readObject();
System.out.println("Server recieved login message!");
if(message.getNumber() == 0){
name = message.getName();
synchronized(names){
if(!names.contains(name)){
names.add(name);
break;
}else{
Message nameTaken = new Message(null, 3);
sendMessage(out, nameTaken);
}
}
}
}
synchronized(outputs){
outputs.add(out);
}
for(ObjectOutputStream output: outputs){
Message response = new Message(name, name + " has logged on.", 0);
sendMessage(output, response);
}
while(true){
System.out.println("Waiting for message...");
Message message = (Message) in.readObject();
Message response = null;
if(message.getNumber() == 1 && message.getMessage() != null){
response = new Message(message.getName(),
message.getMessage(), 1);
}else if(message.getNumber() == 2){
response = new Message(message.getName(), message.getName() +
" has logged off.", 2);
loggedOut = true;
}
for(ObjectOutputStream output: outputs){
sendMessage(output, response);
}
if(loggedOut) break;
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally {
if(name != null) names.remove(name);
if(out != null) outputs.remove(out);
try{
socket.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
private void sendMessage(ObjectOutputStream out, Message message){
ObjectOutputStream outPutMessage = out;
Message response = message;
try {
outPutMessage.writeObject(response);
outPutMessage.flush();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
Client class:
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class ChatClient extends JFrame {
private JTextField inputField;
private JTextField nameField;
private JTextArea textArea;
private JButton loginButton;
private JButton logoutButton;
private JButton connectButton;
private JScrollPane textScroll;
private JScrollPane listScroll;
private JPanel textPanel;
private JPanel connectPanel;
private JPanel listPanel;
private JPanel inputPanel;
private JPanel namePanel;
private JPanel inputAndDisplayPanel;
private JPanel listAndLogoutPanel;
private ArrayList<String> stringList;
private JList list;
private final int CELL_WIDTH = 100;
private ObjectOutputStream out;
private ObjectInputStream in;
private JFrame chatFrame;
private ChatClient client;
private String name;
private final int PORT = 4000;
private boolean needServerData;
private boolean loggedIn;
private boolean previouslyLoggedIn;
private String serverAddress = null;
private Socket socket = null;
private void run() throws IOException, ClassNotFoundException{
needServerData = true;
loggedIn = true;
while(true){
//Loops before a user is logged in, verifies that the host is usable
while (socket == null) {
if (needServerData) {
try {
connectButton.setEnabled(false);
serverAddress = JOptionPane.showInputDialog(client,
"Enter server address: ", "Server Address",
JOptionPane.QUESTION_MESSAGE);
if(serverAddress == null){
JOptionPane.showMessageDialog(client,
"Click 'Connect' to re-enter server address.",
"Info", JOptionPane.PLAIN_MESSAGE);
needServerData = false;
connectButton.setEnabled(true);
}else if(serverAddress.equals("")){
JOptionPane.showMessageDialog(client,
"Invalid input! Enter a valid server address.",
"Error", JOptionPane.ERROR_MESSAGE);
}else {
socket = new Socket(serverAddress, PORT);
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
loginButton.setEnabled(true);
logoutButton.setEnabled(false);
nameField.setEnabled(true);
connectButton.setEnabled(false);
}
} catch (UnknownHostException e1) {
JOptionPane.showMessageDialog(client,
"Error: Unknown host!", "Error",
JOptionPane.ERROR_MESSAGE);
}
}
}
/*Loops after the user is logged in (will output to the textarea that that user logged in),
* reads in messages from server to append to the textarea and also determines if a user is
* logging out. Changes editable/enabled of buttons and text fields accordingly.
*/
if(loggedIn) {
Message message = (Message) in.readObject();
if (message.getNumber() == 1) {
textArea.append(message.getName() + ": "
+ message.getMessage() + "\n");
} else if (message.getNumber() == 0) {
inputField.setEditable(true);
textArea.append(message.getMessage() + "\n");
loginButton.setEnabled(false);
logoutButton.setEnabled(true);
} else if (message.getNumber() == 2) {
inputField.setText(null);
inputField.setEditable(false);
nameField.setText(null);
nameField.setEnabled(false);
connectButton.setEnabled(true);
logoutButton.setEnabled(false);
loggedIn = false;
previouslyLoggedIn = true;
textArea.append(message.getMessage() + "\n");
System.out.println("Socket: " + socket);
} else {
JOptionPane.showMessageDialog(client,
"Error: That name is taken!", "Error",
JOptionPane.ERROR_MESSAGE);
}
}
}
}
private String getServerAddress(){
return JOptionPane.showInputDialog(client, "Enter server address: ",
"Server Address", JOptionPane.QUESTION_MESSAGE);
}
public static void main(String[] args) throws IOException, ClassNotFoundException{
ChatClient client = new ChatClient();
try {
client.run();
} catch (IOException e) {
e.printStackTrace();
}
}
public ChatClient(){
//GUI Formatting Stuff
inputField = new JTextField(30);
nameField = new JTextField(10);
textArea = new JTextArea(25, 30);
loginButton = new JButton("Login");
logoutButton = new JButton("Logout");
connectButton = new JButton("Connect");
textScroll = new JScrollPane(textArea,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
textPanel = new JPanel();
listPanel = new JPanel();
inputPanel = new JPanel();
namePanel = new JPanel();
connectPanel = new JPanel();
textArea.setEditable(false);
textPanel.add(textScroll);
stringList = new ArrayList<String>();
list = new JList(stringList.toArray());
list.setFixedCellWidth(CELL_WIDTH);
listScroll = new JScrollPane(list);
listPanel.add(listScroll);
listAndLogoutPanel = new JPanel(new BorderLayout());
listAndLogoutPanel.add(listPanel, BorderLayout.CENTER);
listAndLogoutPanel.add(logoutButton, BorderLayout.SOUTH);
listAndLogoutPanel.add(loginButton, BorderLayout.NORTH);
inputField.setEditable(false);
inputPanel.add(inputField);
inputAndDisplayPanel = new JPanel(new BorderLayout());
inputAndDisplayPanel.add(textPanel, BorderLayout.CENTER);
inputAndDisplayPanel.add(inputPanel, BorderLayout.SOUTH);
nameField.setEnabled(false);
loginButton.setEnabled(false);
logoutButton.setEnabled(false);
namePanel.setLayout(new FlowLayout(FlowLayout.LEFT));
namePanel.add(new JLabel("Name: "));
namePanel.add(nameField);
connectPanel.add(connectButton);
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.add(namePanel, BorderLayout.WEST);
topPanel.add(connectPanel, BorderLayout.EAST);
JPanel centerPanel = new JPanel(new BorderLayout());
centerPanel.add(inputAndDisplayPanel, BorderLayout.CENTER);
centerPanel.add(topPanel, BorderLayout.NORTH);
JPanel eastPanel = new JPanel(new BorderLayout());
eastPanel.add(listAndLogoutPanel, BorderLayout.CENTER);
setLayout(new BorderLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
add(centerPanel, BorderLayout.CENTER);
add(eastPanel, BorderLayout.EAST);
pack();
setLocationRelativeTo(null);
//Listeners
loginButton.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
name = nameField.getText();
if(name.trim().length() < 3 || name.length() > 15 || name == null){
JOptionPane.showMessageDialog(client,
"Error: Name must be between 3 and 15 characters long.", "Error",
JOptionPane.ERROR_MESSAGE);
}else{
Message message = new Message(name, 0);
try {
out.writeObject(message);
out.flush();
} catch (IOException e1) {
e1.printStackTrace();
}
loggedIn = true;
}
}
});
connectButton.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
needServerData = true;
if(previouslyLoggedIn) socket = null;
}
});
inputField.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
Message message = new Message(name, inputField.getText(), 1);
try {
out.writeObject(message);
out.flush();
} catch (IOException e1) {
e1.printStackTrace();
}
inputField.setText(null);
}
});
logoutButton.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
Message message = new Message(name, 2);
try {
out.writeObject(message);
out.flush();
} catch (IOException e1) {
e1.printStackTrace();
}
inputField.setText(null);
}
});
}
}
Message class:
import java.io.Serializable;
public class Message implements Serializable{
private int number;
private String message;
private String name;
public Message(String name, int number){
this.name = name;
this.number = number;
}
public Message(String name, String message, int number){
this.message = message;
this.number = number;
this.name = name;
}
public boolean isLogin(){
if(number == 0) return true;
return false;
}
public boolean isMessage(){
if(number == 1) return true;
return false;
}
public boolean isLogout(){
if(number == 2) return true;
return false;
}
public int getNumber() {
return number;
}
public String getMessage() {
return message;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I know this is a big block of code and not that neatly documented/formatted, so I apologize for that. I'm just posting the whole thing so you can duplicate the problem by running the code in it's entirety. Additionally, ignore the JList as I haven't gotten to that yet since I encountered and haven't been able to resolve the logging off/socket issue. To recreate the bug, go through the following steps:
Run the Server class
Run a client class, enter "localhost" as the server address, then enter a name and click log-in
Run another client class and follow step 2
Click log-off on one of the client classes, and you'll see the other is also logged off.
Thanks in advance for any help, I appreciate it!
In your ChatClient class, you need to change the line
} else if (message.getNumber() == 2) {
to
} else if (message.getNumber() == 2 && message.getName().equals(name)) {
Because the way it is currently, each chat client receives the message that a client has been logged out, and each client is responding to that by logging out. You will need to handle the additional case afterwards that message.getNumber() == 2, because as it stands now you will assume that it means the name was taken.
Im making a chat program.
i got the client to server connection working but i cant get the server to send to all sockets. Since Im using ObjectOutputStream i cant use PrintWriter which was the way I did it before, Heres my code thanks for the help
Server
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Server {
public Server clients[] = new Server[50];
public static String user;
private static final int PORT = 4000;
private static HashSet<String> names = new HashSet<String>();
private static HashSet<PrintWriter> writers = new HashSet<>();
public static void main(String[] args) throws Exception{
System.out.println("The chatroom is running...");
ServerSocket listener = new ServerSocket(PORT);
try{
while(true){
new Handler(listener.accept()).start();
}
}
catch(Exception e){
System.err.println(e);
}
finally{
listener.close();
}
}
private static class Handler extends Thread{
private String name;
private Socket socket;
//private BufferedReader in;
//private PrintWriter out;
public ObjectOutputStream out;
public ObjectInputStream in;
public void send(Message msg) throws IOException{
out.writeObject(msg);
out.flush();
}
public void Announce(String type, String sender, String content){
Message msg = new Message(type, sender, content, "All");
}
public Handler(Socket socket){
this.socket = socket;
}
public void run(){
try {
out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
in = (new ObjectInputStream(socket.getInputStream()));
out.writeObject(new Message("SUBMITNAME", "blank", "blank", "blank"));
while(true){
Message msg = (Message) in.readObject();
if(msg.sender == null){
return;
}
if(!names.contains(msg.sender)){
names.add(msg.sender);
System.out.println(names.toString());
System.out.println("The object is " + msg);
}
break;
}
while(true){
Message msg = (Message) in.readObject();
System.out.println(msg);
names.add(msg.sender);
System.out.println(names.toString());
break;
}
//out.writeObject(new Message("MESSAGE", "Server", "Welcome To the ChatRoom", "c"));
while(true){
Message msg = (Message) in.readObject();
if(msg.type.equals("MESSAGE")){
out.writeObject(new Message("MESSAGE", msg.sender, msg.content, "all"));
System.out.println(msg.sender + ": " + msg.content);
}
}
}
catch (Exception e) {
System.err.println(e);
}
finally{
try{
socket.close();
System.out.println("Socket has closed");
}
catch(IOException e){
System.err.println("Problem closing socket!");
}
}
}
}
}
Client
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.Socket;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.text.DefaultCaret;
import static javax.swing.text.DefaultCaret.ALWAYS_UPDATE;
public class Client implements Serializable{
//private BufferedReader in;
//private PrintWriter out;
ObjectOutputStream out;
ObjectInputStream in;
String name;
JFrame frame = new JFrame("Client Box");
JTextField textField = new JTextField(40);
JTextArea messageArea = new JTextArea(8,40);
JScrollPane scroll = new JScrollPane(messageArea);
ArrayList<String> list = new ArrayList();
public Client(){
textField.setEditable(false);
messageArea.setEditable(false);
messageArea.setWrapStyleWord(true);
messageArea.setLineWrap(true);
DefaultCaret caret = (DefaultCaret) messageArea.getCaret();
caret.setUpdatePolicy(ALWAYS_UPDATE);
//frame.setLayout(new BorderLayout());
frame.getContentPane().add(textField, BorderLayout.SOUTH);
frame.getContentPane().add(scroll, BorderLayout.CENTER);
frame.pack();
textField.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
try{
//Message msg = new Message("MESSAGE", name, textField.getText(), "all");
//out.writeObject(msg);
sendAll("MESSAGE", name, textField.getText());
textField.setText("");
}catch(IOException ex){System.err.println(ex.printStackTrace()};
}
});
}
public void sendAll(String type, String sender, String content) throws IOException{
Message msg = (new Message(type, sender, content, "all"));
out.writeObject(msg);
out.flush();
}
private String getName(){
return JOptionPane.showInputDialog(frame, "Your Screen Name?", "Please Enter Screen Name: "
, JOptionPane.PLAIN_MESSAGE);
}
private String getMessage(){
return JOptionPane.showInputDialog(frame, "Your message?", "Please Enter Screen Name: "
, JOptionPane.PLAIN_MESSAGE);
}
private void run() throws IOException, ClassNotFoundException{
//String address = getServerAddress();
Socket socket = new Socket("localhost", 4000);
in = (new ObjectInputStream(socket.getInputStream()));
out = new ObjectOutputStream(socket.getOutputStream());
Message temp = (Message) in.readObject();
if(temp.type.equals("SUBMITNAME")){
textField.setEditable(true);
name = getName();
sendAll(name, "a", " b");
}
while(true){
Message msg = (Message) in.readObject();
messageArea.append(msg.sender + ": " + msg.content + "\n");
}
}
public static void main(String[] args) throws ClassNotFoundException{
Client client = new Client();
client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.frame.setLocationRelativeTo(null);
client.frame.setVisible(true);
try {
try {
client.run();
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
I didn't realize until now that my disconnect button on my program was failing. If I have 3 clients up, and any of them click disconnect, then only the last client gets disconnected. How do I select which instance I need to close? If out of the 3 users I want to remove the first one..
server:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class Server {
private Set<Socket> sockets = new HashSet<Socket>();
private Set<String> names = new HashSet<String>();
private Socket sock;
private static int port;
private Calendar cal = Calendar.getInstance();
private SimpleDateFormat date = new SimpleDateFormat("dd/mm/yyyy hh:mm:ss");
public Server(int input) {
port = input;
}
public static void main(String[] args) {
/*
* user defines port number, server initialized
*/
System.out.println("enter a port");
Scanner input = new Scanner(System.in);
port = input.nextInt();
new Server(port).go();
input.close();
}
public void go() {
try {
/*
* wait for connections, add connections to Set, setup streams per
* connection in new threads
*/
System.out.println("waiting for connetion");
#SuppressWarnings("resource")
ServerSocket serverSocket = new ServerSocket(port);
while (true) {
sock = serverSocket.accept();
sockets.add(sock);
Thread t = new Thread(new ClientHandler(sock));
t.start();
System.out.println("connected: " + sock.getInetAddress());
}
} catch (IOException ex) {
ex.printStackTrace();
System.out.println("server setup failed");
}
}
class ClientHandler implements Runnable {
/*
* client handler sets up streams
*/
private BufferedReader in;
private PrintWriter out;
private String name;
public ClientHandler(Socket sock) {
try {
in = new BufferedReader(new InputStreamReader(
sock.getInputStream()));
out = new PrintWriter(sock.getOutputStream(), true);
} catch (IOException e) {
e.printStackTrace();
System.out.println("stream setup failed");
}
}
#Override
public void run() {
/*
* First check if user exists, if true than close connection and
* warn user about name. Then relay message to all clients, if user
* DC's than remove the socket from the Set
*/
String message;
try {
name = in.readLine();
if (names.contains(name)) {
System.out.println("duplicate name detected, removing..");
out.println("choose new name and reconnect: "
+ sock.getInetAddress());
sock.close();
sockets.remove(sock);
} else {
names.add(name);
System.out.println("Users active: " + names);
shout("user: " + name + " connected!" + " from "
+ sock.getInetAddress());
}
while ((message = in.readLine()) != null) {
/*
* call method which checks if user tries to enter a command
* such as /laugh or /roll, otherwise relay the message to
* all clients
*/
swich(message);
}
} catch (IOException ex) {
System.out.println("user disconnected: " + name + " "
+ sock.getInetAddress());
shout("user disconnected: " + name + " "
+ sock.getInetAddress());
names.remove(name);
remove(sock);
}
}
public synchronized void shout(String message) {
// send message to all clients in Set
for (Socket sock : sockets) {
try {
PrintWriter writer = new PrintWriter(
sock.getOutputStream(), true);
writer.println(date.format(cal.getTime()) + " " + message
+ "\n");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void swich(String message) throws IOException {
// check if user calls a chat command
// otherwise shout message to all clients
switch (message) {
case "/disconnect":
out.println("disconnected");
remove(sock);
break;
case "/laugh":
String[] laughs = { "HahHA!", "HAHAAH!!!!", "haaaaa!!!",
"hohohoohohahhaa!!!", "huehuehue!" };
shout(name + " " + laughs[(int) (Math.random() * 5)]);
break;
case "/roll":
shout(name + " rolls "
+ Integer.toString((int) ((Math.random() * 6) + 1)));
break;
case "kirby!":
shout("(>'-')> <('-'<) ^(' - ')^ <('-'<) (>'-')>");
break;
default:
shout(message);
System.out.println("client says : "
+ date.format(cal.getTime()) + message);
}
}
}
public void remove(Socket soc) {
try {
soc.close();
sockets.remove(soc);
} catch (IOException e) {
e.printStackTrace();
}
}
}
client:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Client {
private JTextArea tArea;
private JTextField tField;
private JTextField portText;
private JTextField hostText;
private BufferedReader in;
private Socket sock;
private static PrintWriter out;
private static String name;
private String host;
private String port;
public static void main(String[] args) {
System.out.println("Enter username");
Scanner input = new Scanner(System.in);
name = input.nextLine();
input.close();
new Client().go();
}
public void go() {
/*
* build gui
*/
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("hakobChat");
JPanel topPanel = new JPanel();
JLabel portLabel = new JLabel("port");
JLabel hostLabel = new JLabel("host");
portText = new JTextField(6);
hostText = new JTextField(12);
JButton connect = new JButton("connect");
connect.addActionListener(new connectListener());
JButton disconnect = new JButton("disconnect");
disconnect.addActionListener(new disconnectListener());
tField = new JTextField(30);
tField.addActionListener(new sendListener());
tArea = new JTextArea(30, 50);
tArea.setEditable(false);
tArea.setLineWrap(true);
JScrollPane tScroll = new JScrollPane(tArea,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
JButton button = new JButton("send");
button.addActionListener(new sendListener());
topPanel.add(hostLabel);
topPanel.add(hostText);
topPanel.add(portLabel);
topPanel.add(portText);
topPanel.add(connect);
topPanel.add(disconnect);
frame.setSize(300, 500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(topPanel, BorderLayout.NORTH);
frame.getContentPane().add(tScroll, BorderLayout.CENTER);
frame.getContentPane().add(tField, BorderLayout.SOUTH);
frame.getContentPane().add(button, BorderLayout.EAST);
frame.pack();
}
});
}
public void setupNetwork(String host, int port) {
/*
* setup in and out stream send user name to server to check if
* duplicate start thread for incoming messages
*/
try {
sock = new Socket(host, port);
in = new BufferedReader(
new InputStreamReader(sock.getInputStream()));
out = new PrintWriter(sock.getOutputStream(), true);
out.println(name);
showMessage("Connected!");
showMessage("enter /laugh or /roll or kirby! for some fun!");
Thread t = new Thread(new IncomingReader());
t.start();
} catch (IOException ex) {
ex.printStackTrace();
showMessage("please enter valid network");
}
}
class IncomingReader implements Runnable {
// receive messages from server
public void run() {
try {
String message = null;
while ((message = in.readLine()) != null) {
showMessage(message + "\n");
}
} catch (Exception e) {
e.printStackTrace();
showMessage("choose new name and reconnect please");
}
}
}
public synchronized void sendMessage(String message) {
try {
switch (message) {
case "/laugh":
out.println("/laugh");
break;
case "/roll":
out.println("/roll");
break;
case "kirby!":
out.println("kirby!");
break;
default:
out.println("(" + name + ")" + ": " + message);
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("fail send message");
}
}
public void showMessage(final String message) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
tArea.append(message + "\n");
tArea.setCaretPosition(tArea.getDocument().getLength());
// SetCaretPosition forces autos scroll
}
});
}
class sendListener implements ActionListener {
// listens for user to trying to send a message
public void actionPerformed(ActionEvent ev) {
sendMessage(tField.getText());
tField.setText("");
}
}
class disconnectListener implements ActionListener {
public void actionPerformed(ActionEvent ev) {
try {
out.println("/disconnect");
} catch (NullPointerException e) {
showMessage("not connected");
}
}
}
class connectListener implements ActionListener {
public void actionPerformed(ActionEvent ev) {
host = hostText.getText();
port = portText.getText();
if (!host.equals("") && !port.equals("") && port.matches("[1-9]+")) {
// make sure user enters valid inputs
// before setting up network
setupNetwork(host, Integer.parseInt(port));
} else {
showMessage("enter valid network credentials");
}
}
}
}
Also, how do I avoid this "#SuppressWarnings("resource")". If I don't have this eclipse provided warning than the serverSocket is underlined yellow.
You need to save a the Socket used for the client inside of the ClientHandler.
You can do this by simply adding a
private Socket sock;
inside of ClientHandler, and adding:
this.sock = sock;
inside of its constructor.
Currently you're using the Socket saved in the server, which will always be the socket of the last client that connected, rather than the Socket belonging to the current client.
This is just a scoping problem. The Socket sock member shouldn't be part of the Server class. It should be part of the ClientHandler class. One per client.