I am programming a simple multi-threaded client/server chat system. Project requirements specify: "Connection only happens when the connect button is clicked. The disconnect button should disconnect the connection. A user should be able to connect, disconnect, re-connect at will." Basically, I have the connect button hooked-up and running. However, when I attempt to disconnect I get stuck in an infinite loop where the client side (on command line) infinitely prints "Sock closed", while the server side infinitely prints "Message read: null". This has lead me to look into all of my for(;;) loops to somehow close the connections within them, however I cannot figure out how to close the connection within those loops. Please help, this is my first socket programming project and I am super stumped on this one! Thanks all.
Client:
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
public class ClientFrame extends Frame{
public ClientFrame(){
setSize(500,500);
setTitle("Chat Client");
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent We){
System.exit(0);
}
});
add(new ClientPanel(), BorderLayout.CENTER);
setVisible(true);
}
public static void main(String[] args){
new ClientFrame();
}
} // end ClientFrame
class ClientPanel extends Panel implements ActionListener, Runnable{
TextField tf;
TextArea ta;
List list;
Button connect, disconnect;
Socket socketToServer;
PrintWriter pw;
BufferedReader br;
Thread t;
String userName;
public ClientPanel(){
setLayout(new BorderLayout());
tf = new TextField();
ta = new TextArea();
list = new List();
connect = new Button("Connect");
disconnect = new Button("Disconnect");
Panel bPanel = new Panel();
bPanel.add(connect);
disconnect.setEnabled(false);
bPanel.add(disconnect);
tf.addActionListener(this);
add(tf, BorderLayout.NORTH);
add(ta, BorderLayout.CENTER);
add(list, BorderLayout.EAST);
add(bPanel, BorderLayout.SOUTH);
connect.addActionListener(this);
disconnect.addActionListener(this);
} // end ClientPanel constructor
public void actionPerformed(ActionEvent ae){
if (ae.getSource() == tf){
String temp = tf.getText();
pw.println(userName+": "+temp);
tf.setText("");
} else if (ae.getSource() == connect){
if(tf.getText() == null || tf.getText().equals("")){
ta.append("Must enter a name to connect\n");
}else {
userName = tf.getText();
connect.setEnabled(false);
disconnect.setEnabled(true);
tf.setText("");
try{
socketToServer = new Socket("127.0.0.1", 3000);
pw = new PrintWriter(new OutputStreamWriter
(socketToServer.getOutputStream()), true);
br = new BufferedReader(new InputStreamReader
(socketToServer.getInputStream()));
}catch(UnknownHostException uhe){
System.out.println(uhe.getMessage());
}catch(IOException ioe){
System.out.println(ioe.getMessage());
}
}
t = new Thread(this);
t.start();
pw.println(userName);
pw.println(userName +" has entered the chat.");
}else if (ae.getSource()== disconnect){
try{
t.interrupt();
socketToServer.close();
}catch(IOException ioe){
System.out.println(ioe.getMessage());
}
}
} // end actionPerformed
public void run(){
for(;;){
try{
String temp = br.readLine();
ta.append(temp + "\n");
}catch(IOException ioe){
System.out.println(ioe.getMessage());
}
}
} // end run
} // end ClientPanel
Server:
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.awt.*;
public class ThreadedServerWithPresence{
public static void main(String[] args){
ArrayList<ThreadedHandlerWithPresence> handlers;
try{
handlers = new ArrayList<ThreadedHandlerWithPresence>();
ServerSocket s = new ServerSocket(3000);
for(;;){
Socket incoming = s.accept( );
new ThreadedHandlerWithPresence(incoming,
handlers).start();
}
}catch (Exception e){
System.out.println(e);
}
}
}
class ThreadedHandlerWithPresence extends Thread{
Socket incoming;
ArrayList<ThreadedHandlerWithPresence> handlers;
PrintWriter pw;
BufferedReader br;
String userName;
public ThreadedHandlerWithPresence(Socket i,
ArrayList<ThreadedHandlerWithPresence> handlers){
incoming = i;
this.handlers = handlers;
handlers.add(this);
}
public void setUserName(String userName){
this.userName = userName;
}
public String getUserName(){
return userName;
}
public void run(){
try{
br = new BufferedReader(new InputStreamReader
(incoming.getInputStream()));
pw = new PrintWriter(new OutputStreamWriter
(incoming.getOutputStream()),true);
String firstLine = br.readLine();
setUserName(firstLine);
for(;;){
String temp = br.readLine();
System.out.println("Message read: " + temp);
for(int i = 0; i < handlers.size(); i++){
handlers.get(i).pw.println(temp);
}
}
}catch (Exception e){
System.out.println(e);
}finally{
handlers.remove(this);
}
}
}
Client
Your run method does not handle interruptions so the for loop does not end and it continues trying to receive messages.
You must add an action that can be interrupted and throws InterruptedException, Thread.sleep would be a good candidate in this case, also reducing CPU usage (You do not need to check for new messages every single moment).
try {
for (; ; ) {
try {
String temp = br.readLine();
ta.append(temp + "\n");
} catch (IOException ioe) {
System.out.println(ioe.getMessage());
}
Thread.sleep(10);
}
} catch (InterruptedException e) {
System.out.println("Disconnected.");
}
Server
When br.readLine() returns null, that indicates the connection is closed by the client and you should stop receiving messages.
String temp = br.readLine();
if(temp == null)
break;
Related
I am using Java sockets to create a simple chat room and using AWT component for the GUI. I have all functions of the chat room working, it sends and recieves messages to/from all users, etc... One requirement was to make a list that updates as users enter and leave the chat. I have this function working and my solution was to have my server print the current names of the handlers to a file and then the client grabs the names from the file and adds it to the list. To do this, I made a method that I put in a for(;;) loop so the list continuously updates as users enter/ leave the chat. These requirements all work fine...
MY PROBLEM: The next requirement states: "A user should be able to select a single user from the user list. While a name is selected, all messages sent will be private - only sent to that user." I cannot figure out how to get the selected name back to the server so that someone can send messages only to the username that is selected. Is this even possible with the way I handled creating my list? If so do you have any ideas on how to make this possible? I've been stumped on this for a few days and I am almost thinking at this point that it is not possible and I should rethink my logic for the list. If it is not possible, do you have any ideas for a better solution for my list?
Thank you!
Client file:
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
public class ClientFrame extends Frame{
public ClientFrame(){
setSize(500,500);
setTitle("Chat Client");
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent We){
System.exit(0);
}
});
add(new ClientPanel(new FrameContainer(this)), BorderLayout.CENTER);
setVisible(true);
}
public static void main(String[] args){
new ClientFrame();
}
} // end ClientFrame
class ClientPanel extends Panel implements ActionListener, Runnable, ItemListener{
TextField tf;
TextArea ta;
List list;
Button connect, disconnect;
Socket socketToServer;
PrintWriter pw;
BufferedReader br;
Thread t;
String userName;
FrameContainer fc;
public ClientPanel(FrameContainer fc){
setLayout(new BorderLayout());
tf = new TextField();
ta = new TextArea();
list = new List();
this.fc = fc;
connect = new Button("Connect");
disconnect = new Button("Disconnect");
Panel bPanel = new Panel();
bPanel.add(connect);
disconnect.setEnabled(false);
bPanel.add(disconnect);
tf.addActionListener(this);
connect.addActionListener(this);
disconnect.addActionListener(this);
list.addItemListener(this);
add(tf, BorderLayout.NORTH);
add(ta, BorderLayout.CENTER);
add(list, BorderLayout.EAST);
add(bPanel, BorderLayout.SOUTH);
} // end ClientPanel constructor
public void actionPerformed(ActionEvent ae){
if (ae.getSource() == tf){
String temp = tf.getText();
pw.println(userName+": "+temp);
tf.setText("");
} else if (ae.getSource() == connect){
if(tf.getText() == null || tf.getText().equals("")){
ta.append("Must enter a name to connect\n");
}else {
setUsername(tf.getText());
fc.getFrame().setTitle(userName);
connect.setEnabled(false);
disconnect.setEnabled(true);
tf.setText("");
try{
socketToServer = new Socket("127.0.0.1", 3000);
pw = new PrintWriter(new OutputStreamWriter
(socketToServer.getOutputStream()), true);
br = new BufferedReader(new InputStreamReader
(socketToServer.getInputStream()));
}catch(UnknownHostException uhe){
System.out.println(uhe.getMessage());
}catch(IOException ioe){
System.out.println(ioe.getMessage());
}
}
t = new Thread(this);
t.start();
pw.println(userName);
pw.println(userName +" has entered the chat.");
}else if (ae.getSource() == disconnect){
try{
pw.println(userName +" has left the chat.");
list.removeAll();
fc.getFrame().setTitle("Chat Client");
t.interrupt();
br.close();
pw.close();
socketToServer.close();
connect.setEnabled(true);
disconnect.setEnabled(false);
}catch(IOException ioe){
System.out.println(ioe.getMessage());
}
}
} // end actionPerformed
public void itemStateChanged(ItemEvent ie){
if(ie.getStateChange() == ItemEvent.SELECTED){
String user = list.getSelectedItem();
}else if(ie.getStateChange() == ItemEvent.DESELECTED){
break;
}
} // end itemStateChanged
public void run(){
try {
for (;;) {
if(socketToServer.isClosed() == true) {
break;
}
setList();
try {
String temp = br.readLine();
ta.append(temp + "\n");
} catch (IOException ioe) {
System.out.println(ioe.getMessage());
}
Thread.sleep(10);
}
} catch (InterruptedException e) {
System.out.println("Disconnected.");
}
} // end run
public void setList(){
list.removeAll();
try{
BufferedReader br = new BufferedReader(
new FileReader("onlinelist.txt"));
String line;
while((line = br.readLine()) != null){
this.list.add(line);
}
br.close();
}catch(FileNotFoundException fnfe){
System.out.println(fnfe.getMessage());
}catch(IOException ioe){
System.out.println(ioe.getMessage());
}
} // end setList
public void setUsername(String userName){
this.userName = userName;
}
public String getUsername(){
return userName;
}
} // end ClientPanel
// Container class to change title of frame
class FrameContainer{
ClientFrame f;
public FrameContainer(ClientFrame f){
setFrame(f);
}
public ClientFrame getFrame(){
return f;
}
public void setFrame(ClientFrame f){
this.f = f;
}
}
Server file:
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.awt.*;
public class ThreadedServerWithPresence{
public static void main(String[] args){
ArrayList<ThreadedHandlerWithPresence> handlers;
try{
handlers = new ArrayList<ThreadedHandlerWithPresence>();
ServerSocket s = new ServerSocket(3000);
for(;;){
Socket incoming = s.accept();
new ThreadedHandlerWithPresence(incoming,
handlers).start();
}
}catch (Exception e){
System.out.println(e);
}
}
}
class ThreadedHandlerWithPresence extends Thread{
Socket incoming;
ArrayList<ThreadedHandlerWithPresence> handlers;
PrintWriter pw;
BufferedReader br;
String userName;
ArrayList<String> list;
public ThreadedHandlerWithPresence(Socket i,
ArrayList<ThreadedHandlerWithPresence> handlers){
incoming = i;
this.handlers = handlers;
handlers.add(this);
list = new ArrayList<String>();
}
public void setUserName(String userName){
this.userName = userName;
}
public String getUserName(){
return userName;
}
public void run(){
try{
br = new BufferedReader(new InputStreamReader
(incoming.getInputStream()));
pw = new PrintWriter(new OutputStreamWriter
(incoming.getOutputStream()),true);
setUserName(br.readLine());
createList();
for(;;){
String temp = br.readLine();
if(temp == null)
break;
System.out.println("Message read: " + temp);
for(int i = 0; i < handlers.size(); i++){
handlers.get(i).pw.println(temp);
}
}
}catch (Exception e){
System.out.println(e);
}finally{
handlers.remove(this);
createList();
}
}
public void createList(){
try{
PrintWriter p = new PrintWriter(
new FileWriter("onlinelist.txt"));
for(int i = 0; i < handlers.size(); i++){
p.println(handlers.get(i).getUserName());
}
p.close();
}catch(IOException ioe){
System.out.println(ioe.getMessage());
}
}
}
so here is my code :
Server.java
import java.io.*;
import java.net.*;
import java.util.*;
class Server implements Runnable{
Socket connectionSocket;
public static Vector clients=new Vector();
public Server(Socket s){
try{
System.out.println("Client Got Connected " );
connectionSocket=s;
}catch(Exception e){e.printStackTrace();}
}
public void run(){
try{
BufferedReader reader =
new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
BufferedWriter writer=
new BufferedWriter(new OutputStreamWriter(connectionSocket.getOutputStream()));
clients.add(writer);
while(true){
String data1 = reader.readLine().trim();
System.out.println("Received : "+data1);
for (int i=0;i<clients.size();i++){
try{
BufferedWriter bw= (BufferedWriter)clients.get(i);
bw.write(data1);
bw.write("\r\n");
bw.flush();
}catch(Exception e){e.printStackTrace();}
}
}
}catch(Exception e){e.printStackTrace();}
}
public static void main(String argv[]) throws Exception{
System.out.println("Threaded Chat Server is Running " );
ServerSocket mysocket = new ServerSocket(5555);
while(true){
Socket sock = mysocket.accept();
Server server=new Server(sock);
Thread serverThread=new Thread(server);
serverThread.start();
}
}
}
mychat.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class mychat implements Runnable
{
public JTextField tx;
public JTextArea ta;
public String login="Imed";
BufferedWriter writer;
BufferedReader reader;
public mychat(String l)
{
login=l;
ClientName z = new ClientName();
JFrame f=new JFrame(z.getName()+"'s Chat");
f.setSize(400,400);
JPanel p1=new JPanel();
p1.setLayout(new BorderLayout());
JPanel p2=new JPanel();
p2.setLayout(new BorderLayout());
tx=new JTextField();
p1.add(tx, BorderLayout.CENTER);
JButton b1=new JButton("Send");
p1.add(b1, BorderLayout.EAST);
ta=new JTextArea();
p2.add(ta, BorderLayout.CENTER);
p2.add(p1, BorderLayout.SOUTH);
f.setContentPane(p2);
try
{
Socket socketClient= new Socket("localhost",5555);
writer= new BufferedWriter(new OutputStreamWriter(socketClient.getOutputStream()));
reader =new BufferedReader(new InputStreamReader(socketClient.getInputStream()));
}
catch(Exception e){e.printStackTrace();}
b1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ev)
{
String s=login+" : "+tx.getText();
tx.setText("");
try
{
writer.write(s);
writer.write("\r\n");
writer.flush();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
);
f.setVisible(true);
}
public void run()
{
try
{
String serverMsg="";
while((serverMsg = reader.readLine()) != null)
{
System.out.println("from server: " + serverMsg);
ta.append(serverMsg+"\n");
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
startclient.java
public class startclient
{
public static void main(String [] args)
{
try
{
ClientName n = new ClientName();
mychat c=new mychat(n.getName());
Thread t1=new Thread(c);
t1.start();
}
catch(Exception e){e.printStackTrace();}
}
}
And last ClientName.java
import java.util.*;
public class ClientName
{
String name;
public String getName()
{
Scanner sc = new Scanner(System.in);
System.out.print ("Enter your name : ");
name = sc.nextLine();
return name;
}
}
So basically, i want to limit how many client that could join my server(which maximum is 10 client). And if there is another client that want to join the server after it is full, that client will be rejected so it cannot joined.
I think that's it, though if there are any other improvement in other areas at my code it will also be appreciated. Sorry for my bad english
*Oh and sorry since I forget to include it, but somehow when I start the client, it ask the name twice
You can fix main method in your server and add sayGoodBye() as follows:
private static final int CONNECTION_LIMIT = 10;
public static void main(String argv[]) throws Exception {
System.out.println("Threaded Chat Server is Running ");
ServerSocket mysocket = new ServerSocket(5555);
int socketCount = 0;
while (true) {
Socket sock = mysocket.accept();
Server server = new Server(sock);
if (socketCount++ < CONNECTION_LIMIT) {
Thread serverThread = new Thread(server);
serverThread.start();
} else {
// without starting a thread and notifying only new client
server.sayGoodbye();
}
}
}
public void sayGoodbye() throws IOException {
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connectionSocket.getOutputStream()))) {
writer.write("Sorry, new client connections are not accepted, bye for now");
} catch (Exception e) {
e.printStackTrace();
}
connectionSocket.close();
}
Here is my code:
Server.java
import java.io.*;
import java.net.*;
import java.util.*;
class Server implements Runnable{
static int socketCount = 0;
Socket connectionSocket;
public static Vector clients=new Vector();
public Server(Socket s){
try{
System.out.println("Client Got Connected " );
connectionSocket=s;
}catch(Exception e){e.printStackTrace();}
}
public void run(){
try{
BufferedReader reader =
new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
BufferedWriter writer=
new BufferedWriter(new OutputStreamWriter(connectionSocket.getOutputStream()));
clients.add(writer);
while(true){
String data1 = reader.readLine().trim();
System.out.println("Received : "+data1);
for (int i=0;i<clients.size();i++){
try{
BufferedWriter bw= (BufferedWriter)clients.get(i);
bw.write(data1);
bw.write("\r\n");
bw.flush();
}catch(Exception e){e.printStackTrace();}
}
}
}catch(Exception e){e.printStackTrace();}
}
private static final int CONNECTION_LIMIT = 10;
public static void main(String argv[]) throws Exception {
System.out.println("Threaded Chat Server is Running ");
ServerSocket mysocket = new ServerSocket(5555);
while (true) {
Socket sock = mysocket.accept();
Server server = new Server(sock);
if (socketCount++ < CONNECTION_LIMIT) {
Thread serverThread = new Thread(server);
serverThread.start();
} else {
// without starting a thread and notifying only new client
socketCount--;
server.sayGoodbye();
}
}
}
public void sayGoodbye() throws IOException
{
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connectionSocket.getOutputStream())))
{
writer.write("Sorry, a new client connections are exceeding the server limit thus it will not be accepted");
} catch (Exception e)
{
e.printStackTrace();
}
connectionSocket.close();
}
public int getSocket()
{
return socketCount;
}
}
mychat.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class mychat implements Runnable
{
public JTextField tx;
public JTextArea ta;
Server asd = new Server();
public String login="Imed";
BufferedWriter writer;
BufferedReader reader;
public mychat(String l)
{
login=l;
startclient z = new startclient();
JFrame f=new JFrame(z.getName()+"'s Chat");
f.setSize(400,400);
JPanel p1=new JPanel();
p1.setLayout(new BorderLayout());
JPanel p2=new JPanel();
p2.setLayout(new BorderLayout());
tx=new JTextField();
p1.add(tx, BorderLayout.CENTER);
JButton b1=new JButton("Send");
p1.add(b1, BorderLayout.EAST);
ta=new JTextArea();
p2.add(ta, BorderLayout.CENTER);
p2.add(p1, BorderLayout.SOUTH);
f.setContentPane(p2);
try
{
Socket socketClient= new Socket("localhost",5555);
writer= new BufferedWriter(new OutputStreamWriter(socketClient.getOutputStream()));
reader =new BufferedReader(new InputStreamReader(socketClient.getInputStream()));
}
catch(Exception e){e.printStackTrace();}
b1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ev)
{
String s=login+" : "+tx.getText();
tx.setText("");
try
{
writer.write(s);
writer.write("\r\n");
writer.flush();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
);
f.setDefaultCloseOperation (JFrame.DO_NOTHING_ON_CLOSE);
f.addWindowListener(new java.awt.event.WindowAdapter() {
#Override
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
if (JOptionPane.showConfirmDialog(f,
"Are you sure you want to close this window?", "Close Window?",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION){
asd.getSocket() = asd.getSocket() - 1;
System.exit(0);
}
}
});
f.setVisible(true);
}
public void run()
{
try
{
String serverMsg="";
while((serverMsg = reader.readLine()) != null)
{
System.out.println("from server: " + serverMsg);
ta.append(serverMsg+"\n");
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
startclient.java
import java.util.*;
public class startclient
{
static String name;
public static void main(String [] args)
{
try
{
Scanner sc = new Scanner(System.in);
System.out.print ("Enter your name : ");
name = sc.nextLine();
mychat c=new mychat(name);
Thread t1=new Thread(c);
t1.start();
}
catch(Exception e){e.printStackTrace();}
}
public String getName()
{
return name;
}
}
Every time I try to compile the mychat.java, I get this error message:
mychat.java:13: error: constructor Server in class Server cannot be applied to given types;
Server asd = new Server();
^
required: Socket
found: no arguments
reason: actual and formal argument lists differ in length
mychat.java:90: error: unexpected type
asd.getSocket() = asd.getSocket() - 1;
^
required: variable
found: value
2 errors
I want to limit how many clients can join the server, which kind of works, by adding a new integer called socketCount at Server.java and then increasing the count every time there are new clients joining and if the number of clients is exceeding the server limit, it will reject it.
But it seems that even though I already close the client, the socketCount value is still not decreasing and thus a new client could not enter even though I already giving it places.
Which is why I try to fix it by decreasing the socketCount value at mychat.java every time I close the program, but this error happens.
How can I resolve the error?
You can see the error log here:
mychat.java:13: error: constructor Server in class Server cannot be applied to given types;
Server asd = new Server();
That means you have to put the Socket whenever you create the Server instance.
Your constructor here:
public Server(Socket s){
try{
System.out.println("Client Got Connected " );
connectionSocket=s;
}catch(Exception e){e.printStackTrace();}
}
So, put the Socket to your instance and it should work fine.
Besides that, you should format your codes to be more readable. The class/methods should follow the Coding Convention. It will help you in the future.
Hope this help
I have three programs that work together to make a chat room. I have a server, handler and client. I am attempting to have a constant list of online users in the GUI, so if a new client joined the chat they could still see the list of users. This list is a visible list function in the GUI. I have created and array list in the chat handler, but I have no idea how to have the list appear in the GUI. Please help me, I am a beginner.
Server code:
import java.io.*;
import java.net.*;
import java.util.*;
public class ChatServer{
Socket s;
ArrayList<ChatHandler>handlers;
public ChatServer(){
try{
ServerSocket ss = new ServerSocket(2020);
handlers = new ArrayList<ChatHandler>();
for(;;){
s = ss.accept();//wait for a new client to connect
new ChatHandler(s, handlers).start();// spawn a handler for client
}
}catch(IOException ioe){
System.out.println(ioe.getMessage());
}
}
public static void main(String[] args){
ChatServer tes = new ChatServer();
}
}
Handler code:
import java.io.*;
import java.net.*;
import java.util.*;
public class ChatHandler extends Thread{
Socket s;
BufferedReader br;
PrintWriter pw;
String temp;
ArrayList<ChatHandler>handlers;
String nickName;
List<String> myList = new ArrayList<String>()
public ChatHandler(Socket s, ArrayList<ChatHandler>handlers){
this.s = s;
this.handlers = handlers;
this.nickName = nickName;
}
public void run(){
try{
handlers.add(this);// add myself to list
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
pw = new PrintWriter(s.getOutputStream(), true);
temp = "";
System.out.println("Enter a username: ");
nickName = br.readLine();
myList.add(nickName);
System.out.println(nickName+" joined the chat!");
while((temp = br.readLine()) != null){
for (ChatHandler ch : handlers){// broadcast to all clients
ch.pw.println(nickName+":"+" "+temp); //tell each handler in turn to send message to its client
}
System.out.println(temp);
}
}catch(IOException ioe){
System.out.println(ioe.getMessage());
}finally{
handlers.remove(this);//remove myself from list
}
}
}
Client code:
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Scanner;
public class ChatFrame extends Frame{
public ChatFrame(){
setSize(500,500);
setTitle("Chatting with myself");
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent we){
System.exit(0);
}
});
ChatPanel sp = new ChatPanel();
add(sp, BorderLayout.CENTER);
setVisible(true);
}
public static void main(String[] args){
ChatFrame sf = new ChatFrame();
}
}
class ChatPanel extends Panel implements ActionListener, Runnable{
Thread t;
TextField tf;
TextArea ta;
List lst;
Button b;
Socket s;
BufferedReader br;
PrintWriter pw;
String temp;
boolean connected;
public ChatPanel(){
setLayout(new BorderLayout());
tf = new TextField();
tf.addActionListener(this);
add(tf, BorderLayout.NORTH);
ta = new TextArea();
add(ta, BorderLayout.WEST);
lst = new List();
add(lst, BorderLayout.EAST);
b = new Button("Connect");
b.addActionListener(this);
add(b, BorderLayout.SOUTH);
//t = new Thread(this);
}
public void actionPerformed(ActionEvent ae){
if((ae.getSource() == b) && (!connected)){
try{
s = new Socket("127.0.0.1", 2020);
pw = new PrintWriter(s.getOutputStream(), true);
}catch(UnknownHostException uhe){
System.out.println(uhe.getMessage());
}catch(IOException ioe){
System.out.println(ioe.getMessage());
}
connected = true;
t = new Thread(this);
//b.setEnabled(false);
b.setLabel("Disconnect");
t.start();
}else if((ae.getSource() == b) && (connected)){
connected = false;
try{
s.close(); //no buffering so, ok
}catch(IOException ioe){
System.out.println(ioe.getMessage());
}
//System.exit(0);
b.setLabel("Connect");
}else{
temp = tf.getText();
pw.println(temp);
tf.setText("");
}
}
public void run(){
try{
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
ta.append("Please enter a username"+"\n");
while(((temp = br.readLine()) != null) && connected){
ta.append(temp + "\n");
temp = "";
}}catch(IOException ioe){
System.out.println(ioe.getMessage());
}
}
}
public ChatFrame(){
setSize(500,500);
setTitle("Chatting with myself");
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent we){
System.exit(0);
}
});
ChatPanel sp = new ChatPanel();
add(sp, BorderLayout.CENTER);
add(new JList(YouArrayList.toArray() , BorderLayout.EAST) ;
setVisible(true);
}
I assume your ArrayList has the user correctly.
also you can refer to JList post https://docs.oracle.com/javase/tutorial/uiswing/components/list.html
You need four methods in order to achieve your goal: (1) An ArrayList to hold all nicknames. (2) An Accessor (getter) to fetch your nickname list into your GUI. (3) A Mutator (Setter) to add onto the Array of nicknames. (4) A method to remove or update nicknames from the Array if they disconnect from the chat.
Summary; you need to create three methods and a List in the Server code. You will call these methods in your Client code as needed. You will also need an instance of the Server whenever you want access its methods from outside its class. See below code and use as a reference.
//Adds nickname to myList
public void AddUserName(String name){
myList.add(name);
}
//Removes disconnected nicknames from myList
public void RemoveUserName(String name){
for( int i = 0; i < myList.size(); i++ ){
if(myList(i) == name){
myList.remove(i);
}
}
}
//Returns all nicknames in myList
public ArrayList getUsersOnline(){
return usersOnline;
}
So in your Client code, you will write something like this: cs.getUsersOnline();. You may also need to loop through and append to your list on the Client side. For example see below:
for(int i=0; i < myList.size(); i++){
list.add(ArrayList(i));
}
I hope I'm able to help.
This is the code that i am using (its not mine)
import java.io.*;
import java.net.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SimpleChatClient {
JTextArea incoming;
JTextField outgoing;
BufferedReader reader;
PrintWriter writer;
Socket sock;
public void go() {
JFrame frame = new JFrame("Ludicrously Simple Chat Client");
JPanel mainPanel = new JPanel();
incoming = new JTextArea(15, 50);
incoming.setLineWrap(true);
incoming.setWrapStyleWord(true);
incoming.setEditable(false);
JScrollPane qScroller = new JScrollPane(incoming);
qScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
qScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
outgoing = new JTextField(20);
JButton sendButton = new JButton("Send");
sendButton.addActionListener(new SendButtonListener());
mainPanel.add(qScroller);
mainPanel.add(outgoing);
mainPanel.add(sendButton);
frame.getContentPane().add(BorderLayout.CENTER, mainPanel);
setUpNetworking();
Thread readerThread = new Thread(new IncomingReader());
readerThread.start();
frame.setSize(650, 500);
frame.setVisible(true);
}
private void setUpNetworking() {
try {
sock = new Socket("127.0.0.1", 5000);
InputStreamReader streamReader = new InputStreamReader(sock.getInputStream());
reader = new BufferedReader(streamReader);
writer = new PrintWriter(sock.getOutputStream());
System.out.println("networking established");
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
public class SendButtonListener implements ActionListener {
public void actionPerformed(ActionEvent ev) {
try {
writer.println(outgoing.getText());
writer.flush();
}
catch (Exception ex) {
ex.printStackTrace();
}
outgoing.setText("");
outgoing.requestFocus();
}
}
public static void main(String[] args) {
new SimpleChatClient().go();
}
class IncomingReader implements Runnable {
public void run() {
String message;
try {
while ((message = reader.readLine()) != null) {
System.out.println("client read " + message);
incoming.append(message + "\n");
}
} catch (IOException ex)
{
ex.printStackTrace();
}
}
}
}
My question is in the incoming reader class
Why does this line---- while ((message = reader.readLine()) != null)
never return null?
Supposedly, the thread went to check this line and on the other side there are no messages for the client, then shouldn't the above line return null?
Can anyone explain a bit of what's going on? I do know about socket connections and all
I just want to know what's going on with getting incoming messages.
You are using blocking functions such as BufferedReader.readLine(). This will block until there is something to read. It won't "check the device and return null if nothing is returned".
You can check if there is any incoming data using BufferedReader.available() and call readLine() if the result is > 0.