I am building an application on Socket programming in swing in which server listens for clients and if a client is connected I want
A button should be added for each client if connected on server screen
Add a listener on each button.For example add Send Message function for each client
I have created a thread in server which listens for client connections but I can not add jbutton at runtime.
Please reply.
Is that what you need ? :
import javax.swing.*;
import java.awt.event.*;
public class NewButtonOnRunTime {
static JPanel panel;
static JFrame frame;
public static void main(String[] args){
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
frame = new JFrame("Add Buttons");
JButton button = new JButton("Simulate new Client");
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
JButton jb = new JButton("A new Client");
jb.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "This is an button action");
}
});
panel.add(jb);
frame.revalidate();
}
});
panel = new JPanel();
panel.add(button);
frame.add(panel);
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
Assuming you already have some kind of isConnected bool,
if(isConnected){
JButton runTimeButton = new JButton();
runTimeButton.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
//do all the things you need to do in here,
//alternatively, define this inner class somewhere else and pass in
// an instance of it
}
});
frame.add(runTimeButton);
}
Based on ServerSocket communication in java (i.e. TCP), if a client is connected to the server with a particular port say 5555, no other clients will not be able to connect to the server with the same port at the same time because the port is already in use. So, each client should be using different port if you want to get simultaneous communication with the clients.
Look at this sample code, it adds JButton at runtime when a new client is connected :
(run client code and server code in separate machine connected together)
Server code
package com.test.socket;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
public class ServerFrame extends JFrame {
private Map<Integer, SocketVO> serverSocketMap;
private int startingPort = 5555;
public ServerFrame() {
}
public ServerFrame(String title) {
super(title);
setSize(Toolkit.getDefaultToolkit().getScreenSize());
setLayout(new FlowLayout());
initComponents();
serverSocketMap = new HashMap<Integer, SocketVO>();
keepStartServerSocket();
setVisible(true);
}
private JTextArea area = null;
private void initComponents() {
area = new JTextArea(20, 20);
add(area);
// addDynamicButton();
}
private void addDynamicButton(final int port) {
JButton button = new JButton("Client on " + port + " port");
add(button);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
Socket socket = serverSocketMap.get(port).getSocket();
try {
String content = area.getText();
socket.getOutputStream().write(content.getBytes());
System.out.println("seding text area content to " + port);
System.out.println(content);
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
class SocketVO {
private ServerSocket serverSocket;
private Socket socket;
public ServerSocket getServerSocket() {
return serverSocket;
}
public void setServerSocket(ServerSocket serverSocket) {
this.serverSocket = serverSocket;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
}
private void keepStartServerSocket() {
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
System.out.println("waiting for a client at port "
+ startingPort);
openServerSocket(startingPort);
startingPort++;
}
}
}).start();
}
private void openServerSocket(final int port) {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
final Socket socket = serverSocket.accept();
SocketVO socketVO = new SocketVO();
socketVO.setServerSocket(serverSocket);
socketVO.setSocket(socket);
serverSocketMap.put(port, socketVO);
addDynamicButton(port);
checkForCosing(port, socket);
} catch (IOException e) {
e.printStackTrace();
}
}
private void checkForCosing(final int port, final Socket socket) {
new Thread(new Runnable() {
#Override
public void run() {
InputStream inputStream = null;
try {
inputStream = socket.getInputStream();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
byte[] b = new byte[1024];
int read = 0;
try {
StringBuilder builder = new StringBuilder();
while ((read = inputStream.read(b)) != -1) {
builder.append(new String(b));
}
if (builder.toString().equals("close")) {
closeServerSocket(port);
System.out.println("server port " + port + " closed");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
/**
* the method to close corresponding sockets
*
* #param port
*/
private void closeServerSocket(int port) {
Socket socket = serverSocketMap.get(port).getSocket();
ServerSocket serverSocket = serverSocketMap.get(port).getServerSocket();
try {
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new ServerFrame("Server Socket Frame");
}
}
Client code :
package com.test.socket;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
private int startingPort = 5550;
private void bindToServer() {
while(true) {
try {
Socket socket = new Socket("127.0.0.1", startingPort);
InputStream inputStream = null;
try {
inputStream = socket.getInputStream();
} catch (IOException e1) {
e1.printStackTrace();
}
byte[] b = new byte[1024];
int read = 0;
try {
StringBuilder builder = new StringBuilder();
while((read = inputStream.read(b)) != -1) {
builder.append(new String(b));
}
System.out.println("message from server : "+builder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
startingPort++;
}
if (startingPort == 5580) {
}
}
}
public static void main(String[] args) {
new Client().bindToServer();
}
}
As per your last comment:
I have tested the program with two clients. The server is connected to two clients successfully. But buttons are not added at runtime for each client.
You are able to connect with multiple client and you have added a button also but it's not visible on the server.
Calling validate() again on JFrame will solve your problem after adding new JButton.
public class Test extends JFrame {
private JButton field[];
public JButton[] getField() {
return field;
}
public void test(int n) {
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(0, 1));
field = new JButton[n];
for (int i = 0; i < field.length; i++) {
field[i] = new JButton("" + i + "");
field[i].addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("clicked button");
}
});
panel.add(field[i]);
}
add(panel);
}
public static void main(String[] args) {
Test test = new Test();
test.setSize(300, 300);
test.setVisible(true);
test.setLocationRelativeTo(null);
test.test(5);
}
}
Related
Basically I am just writing a socket.
For some reason I keep getting this error though
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at Main.ChatClient.main(ChatClient.java:143)
which is line " String server = args[0]; "
What does the args need to be to fix this issue?
package Main;
import javax.swing.*;
import java.awt.*;
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.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Observable;
import java.util.Observer;
// Class to manage Client chat Box.
public class ChatClient {
Main a = new Main();
/** Chat client access */
static class ChatAccess extends Observable {
private Socket socket;
private OutputStream outputStream;
#Override
public void notifyObservers(Object arg) {
super.setChanged();
super.notifyObservers(arg);
}
/** Create socket, and receiving thread */
public void InitSocket(String server, int port) throws IOException {
socket = new Socket(server, port);
outputStream = socket.getOutputStream();
Thread receivingThread = new Thread() {
#Override
public void run() {
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String line;
while ((line = reader.readLine()) != null)
notifyObservers(line);
} catch (IOException ex) {
notifyObservers(ex);
}
}
};
receivingThread.start();
}
private static final String CRLF = "\r\n"; // newline
/** Send a line of text */
public void send(String text) {
try {
outputStream.write((text + CRLF).getBytes());
outputStream.flush();
} catch (IOException ex) {
notifyObservers(ex);
}
}
/** Close the socket */
public void close() {
try {
socket.close();
} catch (IOException ex) {
notifyObservers(ex);
}
}
}
/** Chat client UI */
static class ChatFrame extends JFrame implements Observer {
private JTextArea textArea;
private JTextField inputTextField;
private JButton sendButton;
private ChatAccess chatAccess;
public ChatFrame(ChatAccess chatAccess) {
this.chatAccess = chatAccess;
chatAccess.addObserver(this);
buildGUI();
}
/** Builds the user interface */
private void buildGUI() {
textArea = new JTextArea(20, 50);
textArea.setEditable(false);
textArea.setLineWrap(true);
add(new JScrollPane(textArea), BorderLayout.CENTER);
Box box = Box.createHorizontalBox();
add(box, BorderLayout.SOUTH);
inputTextField = new JTextField();
sendButton = new JButton("Send");
box.add(inputTextField);
box.add(sendButton);
// Action for the inputTextField and the goButton
ActionListener sendListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
String str = inputTextField.getText();
if (str != null && str.trim().length() > 0)
chatAccess.send(str);
inputTextField.selectAll();
inputTextField.requestFocus();
inputTextField.setText("");
}
};
inputTextField.addActionListener(sendListener);
sendButton.addActionListener(sendListener);
this.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
chatAccess.close();
}
});
}
/** Updates the UI depending on the Object argument */
public void update(Observable o, Object arg) {
final Object finalArg = arg;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textArea.append(finalArg.toString());
textArea.append("\n");
}
});
}
}
public static void main(String[] args) {
System.out.println("troll");
String server = args[0];
System.out.println("reached here");
int port =2222;
ChatAccess access = new ChatAccess();
JFrame frame = new ChatFrame(access);
frame.setTitle("MyChatApp - connected to " + server + ":" + port);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
try {
access.InitSocket(server,port);
} catch (IOException ex) {
System.out.println("Cannot connect to " + server + ":" + port);
ex.printStackTrace();
System.exit(0);
}
}
}
Given:
String server = args[0];
I'd suggest you provide the server name as your first argument to your program
With
public static void main(String[] args)
args is the array of command line args passed in.
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 create chat app one to one by using Java programming language
I faced issue: client can't send a new message until he receives a message from the server.
You should have a multithreaded application.
The client will run 2 threads:
1) Sender thread which will run on send button. You can every time create a new instance of this thread on clicking send button.
2) The receiver thread will keep on running continuously and check the stream for any message. Once it gets a message on stream it will write the same on console.
Will update you shortly with the code.
Thanks
Written this code long back similarly you can write server using other port
package com.clients;
import java.awt.BorderLayout;
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.awt.event.WindowListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class ClientFullDuplex extends JFrame implements ActionListener {
private JFrame jframe;
private JPanel jp1, jp2;
private JScrollPane jsp;
private JTextArea jta;
private JTextField jtf;
private JButton send;
private Thread senderthread;
private Thread recieverthread;
private Socket ds;
private boolean sendflag;
public static void main(String[] args) {
try {
ClientFullDuplex sfd = new ClientFullDuplex();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public ClientFullDuplex() throws UnknownHostException, IOException {
initGUI();
ds = new Socket("127.0.0.1", 1124);
initNetworking();
}
public void initGUI() {
jframe = new JFrame();
jframe.setTitle("Client");
jframe.setSize(400, 400);
jp1 = new JPanel();
jta = new JTextArea();
jsp = new JScrollPane(jta);
jtf = new JTextField();
send = new JButton("Send");
send.addActionListener(this);
jp1.setLayout(new GridLayout(1, 2, 10, 10));
jp1.add(jtf);
jp1.add(send);
jframe.add(jp1, BorderLayout.SOUTH);
jframe.add(jsp, BorderLayout.CENTER);
jframe.setVisible(true);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jta.append("hello client");
}
#Override
public synchronized void addWindowListener(WindowListener arg0) {
// TODO Auto-generated method stub
super.addWindowListener(arg0);
new WindowAdapter() {
#Override
public void windowClosing(WindowEvent arg0) {
// TODO Auto-generated method stub
if (ds != null)
try {
ds.close();
System.exit(0);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
}
public void initNetworking() {
try {
recieverthread = new Thread(r1);
recieverthread.start();
} catch (Exception e) {
e.printStackTrace();
}
}
Runnable r1 = new Runnable() {
#Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()
+ "Reciver Thread Started");
recieveMessage(ds);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Runnable r2 = new Runnable() {
#Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()
+ "Sender Thread Started");
sendMessage(ds);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
public void recieveMessage(Socket rms) throws IOException {
while (true) {
System.out.println(Thread.currentThread().getName()
+ "Reciver Functionality");
BufferedReader br = new BufferedReader(new InputStreamReader(
rms.getInputStream()));
String line = br.readLine();
System.out.println(line);
jta.append("\nServer:"+line);
}
}
public void sendMessage(Socket sms) throws IOException {
System.out.println(Thread.currentThread().getName()
+ "Sender Functionality");
PrintWriter pw = new PrintWriter(sms.getOutputStream(), true);
String sline = jtf.getText();
System.out.println(sline);
pw.println(sline);
jtf.setText("");
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if (e.getSource() == send) {
senderthread = new Thread(r2);
senderthread.start();
}
}
}
This is the code I copied and edited from your earlier post.
The problem is that the input stream from socket is blocking. So my suggestion is to read up on async sockets in java and refactor the code below.
next to that it isn't that difficult to edit posts.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Server {
public static void main(String[] args) {
Server chatServer = new Server(5555);
System.out.println("###Start listening...###");
chatServer.startListening();
chatServer.acceptClientRequest();
}
private ServerSocket listeningSocket;
private Socket serviceSocket;
private int TCPListeningPort;
private ArrayList<SocketHanding> connectedSocket;
public Server(int TCPListeningPort)
{
this.TCPListeningPort = TCPListeningPort;
connectedSocket = new ArrayList<SocketHanding>();
}
public void startListening()
{
try
{
listeningSocket = new ServerSocket(TCPListeningPort);
}
catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void acceptClientRequest()
{
try
{
while (true)
{
serviceSocket = listeningSocket.accept();
SocketHanding _socketHandling = new SocketHanding(serviceSocket);
connectedSocket.add(_socketHandling);
Thread t = new Thread(_socketHandling);
t.start();
System.out.println("###Client connected...### " + serviceSocket.getInetAddress().toString() );
}
}
catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
class SocketHanding implements Runnable
{
private Socket _connectedSocket;
private PrintWriter socketOut;
private InputStream socketIn;
private boolean threadRunning = true;
private String rmsg;
public SocketHanding(Socket connectedSocket) throws IOException
{
_connectedSocket = connectedSocket;
socketOut = new PrintWriter(_connectedSocket.getOutputStream(), true);
socketIn = _connectedSocket.getInputStream();
}
private void closeConnection() throws IOException
{
threadRunning = false;
socketIn.close();
socketOut.close();
_connectedSocket.close();
}
public void sendMessage(String message)
{
socketOut.println(message);
}
private String receiveMessage() throws IOException
{
String t = "";
if (_connectedSocket.getInputStream().available() > 0)
{
byte[] b = new byte[8192];
StringBuilder builder = new StringBuilder();
int bytesRead = 0;
if ( (bytesRead = _connectedSocket.getInputStream().read(b)) > -1 )
{
builder.append(new String(b, 0, b.length).trim());
}
t = builder.toString();
}
return t;
}
#Override
public void run()
{
while (threadRunning)
{
try
{
rmsg = receiveMessage();
System.out.println(rmsg);
if(rmsg.equalsIgnoreCase("bye"))
{
System.out.println("###...Done###");
closeConnection();
break;
}
else
{
String smsg = "";
BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
smsg = keyboard.readLine();
keyboard.close();
sendMessage("Server: "+smsg);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
I've been working on building a chat server to learn about threading and using sockets. I used head first java as a guide (and I'm still confused about a couple of things, which is why I have this question probably :D) and the code below is what I have.
If you read my code, you'll see that I have clients connect to the server by clicking on a "connect" button. When they do that, a new jframe pops up that asks for their preferred name for the chat session. When they input that, it's saved in a String in the client code. My question is, how do I get this name over to the server, and make it so that every time the client sends a message, their name is displayed before their message?
Thank you for the help!!!
(ALSO, if anyone knows a good link that can explain sockets and how socket/client interaction occurs through threads, that would be great!)
server code:
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
public class GameServerOne {
ArrayList clientOutputStreams;
String clientName;
private class ClientThreadHandler implements Runnable {
BufferedReader clientIncomingReader;
Socket socket1;
public ClientThreadHandler(Socket clientSocket2) {
try {
socket1 = clientSocket2;
InputStreamReader clientInputReader = new InputStreamReader(socket1.getInputStream());
clientIncomingReader = new BufferedReader(clientInputReader);
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
String message;
try {
while ((message = clientIncomingReader.readLine()) != null) {
tellEveryone(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void tellEveryone(String message) {
Iterator it = clientOutputStreams.iterator();
while(it.hasNext()) {
try {
PrintWriter writer = (PrintWriter) it.next();
writer.println(message);
writer.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void setUpServer() {
clientOutputStreams = new ArrayList();
try {
ServerSocket gameSocket = new ServerSocket(5151);
//System.out.println("Server Connected");
while (true) {
Socket clientSocket = gameSocket.accept();
PrintWriter writer = new PrintWriter(clientSocket.getOutputStream());
writer.println("User connected");
writer.flush();
clientOutputStreams.add(writer);
Thread t = new Thread(new ClientThreadHandler(clientSocket));
t.start();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
new GameServerOne().setUpServer();
}
}
Client code:
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GameClientOne {
Socket gameSocket;
JFrame inputNameFrame;
JFrame clientFrame;
JTextArea chatArea;
JTextField messageInput;
BufferedReader gameChatReader;
PrintWriter gameChatWriter;
JTextField nameField;
boolean sessionNamePicked = false;
String userSessionName;
BufferedReader gameBufferedReader;
public GameClientOne () {
setUpGUI();
}
public void setUpGUI() {
clientFrame = new JFrame("Game Window");
JPanel mainPanel = new JPanel(new BorderLayout());
JPanel southPanel = new JPanel(new BorderLayout());
JPanel centerPanel = new JPanel(new BorderLayout());
chatArea = new JTextArea();
chatArea.setWrapStyleWord(true);
chatArea.setLineWrap(true);
chatArea.setEditable(false);
JScrollPane chatScroller = new JScrollPane(chatArea);
messageInput = new JTextField();
messageInput.addKeyListener(new MessageInputFieldListener());
JButton sendButton = new JButton("Send");
sendButton.addActionListener(new SendButtonListener());
JPanel westPanel = new JPanel(/*new GridLayout(20, 1)*/);
JPanel eastPanel = new JPanel();
JButton connectButton = new JButton("Connect");
connectButton.addActionListener(new ConnectButtonListener());
connectButton.setPreferredSize(new Dimension(100, 28));
JPanel northPanel = new JPanel(new FlowLayout());
JLabel northTitleLabel = new JLabel("Game Screen");
westPanel.add(connectButton);
chatScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS) ;
chatScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
northPanel.add(northTitleLabel);
centerPanel.add(BorderLayout.CENTER, chatScroller);
southPanel.add(BorderLayout.CENTER, messageInput);
southPanel.add(BorderLayout.EAST, sendButton);
mainPanel.add(BorderLayout.SOUTH, southPanel);
mainPanel.add(BorderLayout.CENTER, centerPanel);
mainPanel.add(BorderLayout.WEST, westPanel);
mainPanel.add(BorderLayout.EAST, eastPanel);
mainPanel.add(BorderLayout.NORTH, northPanel);
clientFrame.add(mainPanel);
clientFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
clientFrame.setSize(450, 600);
clientFrame.setVisible(true);
messageInput.requestFocusInWindow();
}
public void setUpInputNameFrame() {
inputNameFrame = new JFrame("Insert Name");
JPanel mainPanel = new JPanel(new BorderLayout());
nameField = new JTextField();
nameField.addKeyListener(new NameFieldListener());
JButton submitButton = new JButton("Submit");
submitButton.addActionListener(new SubmitButtonListener());
JLabel inputNameLabel = new JLabel("Please pick a name for the chat session");
JPanel northPanel = new JPanel(new FlowLayout());
JPanel southPanel = new JPanel(new BorderLayout());
northPanel.add(inputNameLabel);
southPanel.add(BorderLayout.CENTER, nameField);
southPanel.add(BorderLayout.EAST, submitButton);
mainPanel.add(BorderLayout.NORTH, northPanel);
mainPanel.add(BorderLayout.SOUTH, southPanel);
inputNameFrame.add(mainPanel);
inputNameFrame.setSize(300, 150);
inputNameFrame.setVisible(true);
nameField.requestFocusInWindow();
}
public void connectToGameServer() {
try {
gameSocket = new Socket("127.0.0.1", 5151);
InputStreamReader gameSocketReader = new InputStreamReader(gameSocket.getInputStream());
gameBufferedReader = new BufferedReader(gameSocketReader);
gameChatWriter = new PrintWriter(gameSocket.getOutputStream());
chatArea.append("Connected with name: " + userSessionName + "\n");
Thread incomingTextThread = new Thread(new IncomingTextReader());
incomingTextThread.start();
//System.out.println("Connected to Game");
} catch (Exception e) {
System.out.println("Could not connect to game...");
e.printStackTrace();
}
}
//ALL LISTENER CLASSES BELOW HERE
//main chat page listeners
private class ConnectButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (!sessionNamePicked) {
setUpInputNameFrame();
} else {
chatArea.append("You already connected!\n");
}
}
}
private class SendButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (!sessionNamePicked) {
chatArea.append("Please connect first\n");
messageInput.setText("");
messageInput.requestFocusInWindow();
} else {
try {
gameChatWriter.println(messageInput.getText());
gameChatWriter.flush();
} catch (Exception ex2) {
ex2.printStackTrace();
}
//chatArea.append(userSessionName + ": " + messageInput.getText() + "\n");
messageInput.setText("");
messageInput.requestFocusInWindow();
}
}
}
private class MessageInputFieldListener implements KeyListener {
public void keyPressed(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
if (!sessionNamePicked) {
chatArea.append("Please connect first\n");
messageInput.setText("");
} else {
try {
gameChatWriter.println(messageInput.getText());
gameChatWriter.flush();
} catch (Exception ex2) {
ex2.printStackTrace();
}
//chatArea.append(userSessionName + ": " + messageInput.getText() + "\n");
messageInput.setText("");
}
}
}
}
//pick chat session name listeners: nameField/submitButton
private class NameFieldListener implements KeyListener {
public void keyPressed(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
if (!nameField.getText().isEmpty() && e.getKeyCode() == KeyEvent.VK_ENTER) {
userSessionName = nameField.getText();
sessionNamePicked = true;
connectToGameServer();
inputNameFrame.dispose();
messageInput.requestFocusInWindow();
}
}
}
private class SubmitButtonListener implements ActionListener {
public void actionPerformed (ActionEvent e) {
if (!nameField.getText().isEmpty()) {
userSessionName = nameField.getText();
sessionNamePicked = true;
connectToGameServer();
inputNameFrame.dispose();
messageInput.requestFocusInWindow();
}
}
}
//Runnable implementation for threads
private class IncomingTextReader implements Runnable {
public void run() {
String incomingMessage;
try {
while ((incomingMessage = gameBufferedReader.readLine()) != null) {
chatArea.append(incomingMessage + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
GameClientOne gameClient = new GameClientOne();
}
}
If you want to send more than just a message as you are now, you are going to need a protocol to decide what to do with the string you receive, instead of just sending it to all the other clients.
For example, on the client side to send the client's name you might write NAME:(client's name), and then on the server you would split the string at the : and check if the first part is NAME, and if so set the clients name to the rest of the string. You should think about what other types of data you might want to send aswell and design a protocol that works for it.
Here's an example of how to do the above:
On the client you could add the line gameChatWriter.write("NAME:"+name) (create name first of course) imediatly after the connection is made. Then on the server, instead of calling tellEveryone(message) when the message is recieved create a method called processInput and call it, which might look like this:
private void processInput(String message){
String[] commands=message.split(':');
if(commands[0].equals("NAME")){
clientName=commands[1];
}
else{
tellEveryone(message);
}
}
Right now you only have one String clientName and you will obviously need more for the other clients you want to talk to so I would recommend making the thread handler into a seperate class which you would instantiate for each client and could hold things like that.
After you get this to work you could also create a seperate method to write other things that you want to send to either the client or server and a method to process input on the client side as well. Hope this helps.
I have a client-server communication code. but, I actually want multiple clients communicating with the server not other clients, how should I implement it?
// This is server code:
import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class ServerFile extends JFrame {
private JTextField usertext;
private JTextArea chatwindow;
private ObjectOutputStream output;
private ObjectInputStream input;
private ServerSocket server;
private Socket connection;
public ServerFile() {
super("Admin");
usertext = new JTextField();
usertext.setEditable(false);
usertext.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
sendmessage(event.getActionCommand());
usertext.setText("");
}
});
add(usertext, BorderLayout.SOUTH);
chatwindow = new JTextArea();
add(new JScrollPane(chatwindow));
setSize(300, 250);
setVisible(true);
}
public void startrunning() {
try {
server = new ServerSocket(6789, 100);
while (true) {
try {
waitForConnection();
setupstream();
whilechatting();
} catch (Exception e) {
System.out
.println("\nYou have an error in conversation with client");
} finally {
closecrap();
}
}
} catch (Exception e) {
System.out.println("\nYou have an error in connecting with client");
}
}
private void waitForConnection() throws IOException {
showmessage("\nWaiting for someone to connect");
connection = server.accept();
showmessage("\nNow connected to "
+ connection.getInetAddress().getHostName());
}
private void setupstream() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showmessage("\nStreams are setup");
}
private void whilechatting() throws IOException {
String message = "\nYou are now connected ";
sendmessage(message);
ableToType(true);
do {
try {
message = (String) input.readObject();
showmessage(message);
} catch (Exception e) {
System.out.println("\nError in reading message");
}
} while (!message.equals("CLIENT-END"));
}
private void closecrap() {
showmessage("\nClosing connection");
ableToType(false);
try {
output.close();
input.close();
connection.close();
} catch (Exception e) {
System.out.println("\nError in closing server");
}
}
private void sendmessage(String message) {
try {
chatwindow.append("\nSERVER: " + message);
output.writeObject("\nSERVER: " + message);
output.flush();
} catch (Exception e) {
chatwindow.append("\nError in sending message from server side");
}
}
private void showmessage(final String text) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
chatwindow.append("\n" + text);
}
});
}
private void ableToType(final boolean tof) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
usertext.setEditable(tof);
}
});
}
}
public class Server {
public static void main(String args[]) {
ServerFile server1 = new ServerFile();
server1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
server1.startrunning();
}
}
// and this is the client code:
import javax.swing.JFrame;
import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class ClientFile extends JFrame {
private static final long serialVersionUID = 1L;
private JTextField usertext;
private JTextArea chatwindow;
private ObjectOutputStream output;
private ObjectInputStream input;
private String message="";
private String serverIP;
private ServerSocket server;
private Socket connection;
public ClientFile(String host)
{
super("Client");
serverIP=host;
usertext= new JTextField();
usertext.setEditable(false);
usertext.addActionListener( new ActionListener(){
public void actionPerformed(ActionEvent event){
sendmessage(event.getActionCommand());
usertext.setText("");
}
}
);
add(usertext,BorderLayout.SOUTH);
chatwindow= new JTextArea();
add(new JScrollPane(chatwindow));
setSize(300,250);
setVisible(true);
}
public void startrunning() {
try {
connecttoserver();
setupstream();
whilechatting();
}
catch(Exception e){
System.out.println("\nYou have an error in coversation with server");
}
finally{
closecrap();
}
}
private void connecttoserver() throws IOException{
showmessage("\nAttempting connection");
connection = new Socket(InetAddress.getByName("127.0.0.1"),6789);
showmessage("\nConnected to "+connection.getInetAddress().getHostName());
}
private void setupstream() throws IOException{
output= new ObjectOutputStream(connection.getOutputStream());
output.flush();
input= new ObjectInputStream(connection.getInputStream());
showmessage("\nStreams are good to go");
}
private void whilechatting()throws IOException{
ableToType(true);
do {
try{
message = (String)input.readObject();
showmessage(message);
}
catch(Exception e){
System.out.println("\nError in writing message");
}
} while(!message.equals("SERVER - END"));
}
private void closecrap(){
showmessage("\nClosing....");
ableToType(false);
try{
output.close();
input.close();
connection.close();
}
catch(Exception e){
System.out.println("\nError in closing client");
}
}
private void sendmessage(String message){
try{
chatwindow.append("\nCLIENT: "+message);
output.writeObject("\nCLIENT: "+message);
output.flush();
}
catch(Exception e){
chatwindow.append("\nError in sending message from client side");
}
}
private void showmessage(final String m){
SwingUtilities.invokeLater( new Runnable(){
public void run(){
chatwindow.append("\n"+m);
}});
}
private void ableToType(final boolean tof){
SwingUtilities.invokeLater( new Runnable(){
public void run(){
usertext.setEditable(tof);
}});
}
}
public class Client {
public static void main(String args[])
{
ClientFile obj2= new ClientFile("127.0.0.1");
obj2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
obj2.startrunning();
}
}
Applying multithreading is a good solution, but when I applied, there gets connection extablished between only one client and one server.. Please help me to do this
Applying multithreading is a good solution, but when I applied, there gets connection extablished between only one client and one server.. Please help me to do this
I did not get through (and thus checked) all your code, but I noticed one thing:
in your startrunning() function you:
create a server socket
in an infine loop:
wait for a new connection
when there's a new connection call setupstream()
and chat using whilechatting()
so there, you will get only one new connection that will get its stream set up and chat. You can only have one thread serving your clients, so only the first one arrived will get served, until it releases the thread so another can connect.
You should instead do:
create a server socket
in an infine loop:
wait for a new connection
when there's a new connection:
create a new thread for that connection
call setupstream()
and chat using whilechatting()
There each client will get spawned into their own cosy thread, while the main thread is in its infinite loop waiting for new clients.
HTH