Issue with Java Server class and socket connections - java

I am trying to set up a server class, and i'm running into a issue in which no error is being thrown.
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Server extends JFrame implements Runnable{
private static final long serialVersionUID = 1L;
private JTextField userText;
private JTextArea chatWindow;
private ObjectOutputStream output;
private ObjectInputStream input;
private ServerSocket server;
private Socket connection;
//constructor
public Server(){
super("Server");
userText = new JTextField();
userText.setEditable(false);
userText.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent event){
sendMessage(event.getActionCommand());
userText.setText("");
}
}
);
add(userText, BorderLayout.NORTH);
chatWindow = new JTextArea();
add(new JScrollPane(chatWindow));
setSize(300, 150); //Sets the window size
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public void run(){
try{
server = new ServerSocket(6789, 100); //6789 is a dummy port for testing, this can be changed. The 100 is the maximum people waiting to connect.
while(true){
try{
//Trying to connect and have conversation
waitForConnection();
setupStreams();
whileChatting();
}catch(EOFException eofException){
showMessage("\n Server ended the connection! ");
} finally{
closeConnection(); //Changed the name to something more appropriate
}
}
} catch (IOException ioException){
ioException.printStackTrace();
}
}
//wait for connection, then display connection information
private void waitForConnection() throws IOException{
showMessage(" Waiting for someone to connect... \n");
connection = server.accept();
showMessage(" Now connected to " + connection.getInetAddress().getHostName());
}
//get stream to send and receive data
private void setupStreams() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showMessage("\n Streams are now setup \n");
}
//during the chat conversation
private void whileChatting() throws IOException{
String message = " You are now connected! ";
sendMessage(message);
ableToType(true);
do{
try{
message = (String) input.readObject();
showMessage("\n" + message);
}catch(ClassNotFoundException classNotFoundException){
showMessage("The user has sent an unknown object!");
}
}while(!message.equals("CLIENT - END"));
}
public void closeConnection(){
showMessage("\n Closing Connections... \n");
ableToType(false);
try{
output.close(); //Closes the output path to the client
input.close(); //Closes the input path to the server, from the client.
connection.close(); //Closes the connection between you can the client
}catch(IOException ioException){
ioException.printStackTrace();
}
}
//Send a mesage to the client
private void sendMessage(String message){
try{
output.writeObject("SERVER - " + message);
output.flush();
showMessage("\nSERVER -" + message);
}catch(IOException ioException){
chatWindow.append("\n ERROR: CANNOT SEND MESSAGE, PLEASE RETRY");
}
}
//update chatWindow
private void showMessage(final String text){
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
chatWindow.append(text);
}
}
);
}
private void ableToType(final boolean tof){
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
userText.setEditable(tof);
}
}
);
}
}
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class Menu extends JFrame implements ActionListener{
private static final long serialVersionUID = 1L;
private JButton server;
private JButton client;
private static String Host;
public Menu(){
this.getContentPane().setPreferredSize(new Dimension(300, 300));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(null);
this.pack();
this.setLocationRelativeTo(null);
server = new JButton();
server.setText("server");
server.setBounds(0, 0, 300, 150);
server.addActionListener(this);
client = new JButton();
client.setText("client");
client.setBounds(0, 150, 300, 150);
client.addActionListener(this);
this.add(server);
this.add(client);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == server){
Server s = new Server();
s.run();
}
if(e.getSource() == client){
Host = JOptionPane.showInputDialog("Enter Server I.P.");
Client c = new Client(Host);
c.run();
}
}
public static void main(String[] args){
new Menu();
}
}
The JFrame is created, but can only be exited by the termination button in eclipse, not the default_exit_on_close operation, and is see through (not opaque as it should be). The client class acts the same way, leading me to believe that the issue is the:
Server s = new Server();
s.run();
since if i have the main method call that, everything works fine.

Your constructor can never exit.
This waitForConnection()/setUpStreams() logic is not appropriate. You need an accept loop that just accepts sockets, constructs a Runnable to handle the connection, and starts a thread. That loop should be in a separate run() method and be executed in a separate thread. Not in a constructor.
NB The Socket that is returned by accept() must be a local variable in that loop, otherwise you are liable to run into concurrency problems.

Related

Handle Java Socket connection between 2 JFrames

I'm trying to create a client/server application using sockets, I have 2 JFrames (2 seperate classes) , a user will initially open up the one frame and there's a button to go to the other JFrame, when clicked it disposes the previous frame and opens the new frame.
I'd like to know how I could switch back and forth between these 2 JFrames without my program crashing and needing to forcefully close, I am establishing the connection in the constructor of each JFrame.
try {
server = new Socket("localhost", PORT);
// creates & instantiates objectInput and output streams
getStreams();
} catch (IOException ex) {
System.out.println("error creating socket: " + ex.getMessage());
}
I have these in the constructor of both JFrames
EDIT
Server
public class Testserver {
private ServerSocket serverSocket;
private Socket client;
private final int PORT = 5432;
private ObjectOutputStream objectOutputStream;
private ObjectInputStream objectInputStream;
public Testserver() {
try {
serverSocket = new ServerSocket(PORT);
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
System.out.println("error creating server socket: " + ex.getMessage());
}
}
private void listenForClient() {
try {
System.out.println("Server is running and is waiting/listening for a connection to be established.");
////JOptionPane.showMessageDialog(null, "Server is running and is waiting/listening for a connection to be established." );
client = serverSocket.accept();
System.out.println("A client has connected");
objectOutputStream = new ObjectOutputStream(client.getOutputStream());
objectInputStream = new ObjectInputStream(client.getInputStream());
processClient();
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
}
}
private void processClient() {
do {
try {
String messageFromClient = (String) objectInputStream.readObject();
// check for clients requests and handle them (database etc)
System.out.println("[CLIENT] " + messageFromClient);
} catch (IOException ex) {
Logger.getLogger(Testserver.class.getName()).log(Level.SEVERE, null, ex);
break;
} catch (ClassNotFoundException ex) {
Logger.getLogger(Testserver.class.getName()).log(Level.SEVERE, null, ex);
break;
}
} while (true);
closeConnections();
}
private void closeConnections() {
try {
objectInputStream.close();
objectInputStream.close();
client.close();
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
}
}
public static void main(String[] args) {
new Testserver().listenForClient();
}
}
CustomerGUI
public class CustomerGUI extends JFrame implements ActionListener{
private Socket server;
private ObjectOutputStream objectOutputStream;
private ObjectInputStream objectInputStream;
private JPanel panel1;
private JButton btnAdminGUI;
private final int PORT = 5432;
public CustomerGUI() {
btnAdminGUI = new JButton("Go to Admin GUI");
try {
server = new Socket("localhost", PORT);
System.out.println("Connected to server");
objectOutputStream = new ObjectOutputStream(server.getOutputStream());
objectInputStream = new ObjectInputStream(server.getInputStream());
objectOutputStream.writeObject("from Customer");
objectOutputStream.flush();
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage()););
}
btnAdminGUI.addActionListener(this);
}
public void setGUI() {
add(btnAdminGUI);
setSize(300, 400);
setVisible(true);
}
public static void main(String[] args) {
new CustomerGUI().setGUI();
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == btnAdminGUI) {
new AdminGUI().setGUI();
dispose();
}
}
}
AdminGUI
public class AdminGUI extends JFrame implements ActionListener{
private Socket server;
private ObjectOutputStream objectOutputStream;
private ObjectInputStream objectInputStream;
private JPanel panel1;
private JButton btnCustomerGUI;
private final int PORT = 5432;
public AdminGUI() {
btnCustomerGUI = new JButton("Go to Customer GUI");
try {
server = new Socket("localhost", PORT);
System.out.println("Connected to server");
objectOutputStream = new ObjectOutputStream(server.getOutputStream());
objectInputStream = new ObjectInputStream(server.getInputStream());
objectOutputStream.writeObject("from Admin");
objectOutputStream.flush();
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
}
btnCustomerGUI.addActionListener(this);
}
public void setGUI() {
add(btnCustomerGUI);
setSize(300, 400);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == btnCustomerGUI) {
new CustomerGUI().setGUI();
dispose();
}
}
}
I'll post a solution this because I have done something similar recently, but I don't have a UI for it yet.
The idea is MVC, with two models, a Server and Client and there are two Views, JPanels, which can be displayed in a window/jframe/dialog, whichever is appropriate. The Controller is essentially an api for interacting with the model, for this simple example the controllers will be mixed with the models. I think this example has a lot of flaws, but I think it gives a good idea of what needs to be done.
A button starts a course of action,
serverControls.addActionListener( evt ->{ } );
The button does one of two actions, either it starts the server or it stops the server.
serverLoop.submit( ()->{
server.listen();
//should notify a listener that the server has stopped.
});
serverLoop is another thread of execution, server.listen() is a long running task. It shouldn't return until we want the server to stop listening.
The other button is on the client. It has a similar structure..
clientControls.addActionListener( evt->{
clientLoop.submit( () -> client.connect( server ) );
clientLoop.submit(
() -> SwingUtilities.invokeLater(
() -> response.setText( client.communicate() )
)
);
});
First the client is going to connect, then it communicates.
import javax.swing.*;
import java.util.concurrent.*;
public class ClientServerApp{
static class Server{
volatile boolean available = false;
public void listen(){
try{
available = true;
synchronized( this ){
wait(5000);
}
} catch(Exception e){
e.printStackTrace();
//if the server terminates unexpectedly.
}finally{
available = false;
}
}
public void stopListening(){
}
}
static class Client{
Server connected;
public void connect(Server host){
connected = host;
}
public String communicate(){
if(connected != null){
if(connected.available){
return "connected";
} else{
return "cannot connect";
}
}
return "no host";
}
}
public static void main(String[] args){
Server server = new Server();
Client client = new Client();
ExecutorService serverLoop = Executors.newSingleThreadExecutor();
JPanel serverView = new JPanel();
JButton serverControls = new JButton("start");
serverView.add( serverControls );
serverControls.addActionListener( evt ->{
if(serverControls.getText().equals("start") ){
serverControls.setText("stop");
serverLoop.submit( ()->{
server.listen();
//should notify a listener that the server has stopped.
});
} else{
server.stopListening();
serverLoop.submit( ()->{
//will be run after the listen loop has completed.
SwingUtilities.invokeLater( () - >
serverControls.setText("start")
);
});
}
} );
JPanel clientView = new JPanel();
JButton clientControls = new JButton("connect");
JTextField response = new JTextField(40);
clientView.add( clientControls );
clientView.add(response);
ExecutorService clientLoop = Executors.newSingleThreadExecutor();
System.out.println("creating client action listener");
clientControls.addActionListener( evt->{
clientLoop.submit( () -> client.connect( server ) );
clientLoop.submit( () ->
SwingUtilities.invokeLater(
() -> response.setText( client.communicate() )
)
);
});
JFrame mainWindow = new JFrame();
mainWindow.setContentPane( serverView);
mainWindow.pack();
mainWindow.setVisible(true);
JDialog clientWindow = new JDialog( mainWindow, "Client Window");
clientWindow.setContentPane(clientView);
clientWindow.pack();
clientWindow.setVisible(true);
}
}
In a more complete example, you would probably have a Listener interface, so that your swing gui can response to changes in state of the server or the client, and a controller that manages the threads.

Updating the objects of multiple instances of the same class at the same time

I am trying to develop a GUI based chat-server.I built a client class which has the code to generate the GUI for the client and the methods to write to the server and then to read from the server.The client class writes the message to the buffer of ServerSocket when the send button is clicked.
But the problem is that,after executing more than one client when i write message in the JTextField of a client GUI and then click send then the message gets visible only in the JTextArea of that particular instance of client while JTextArea of other instances of client remain empty i.e no updation takes place in them.
I noticed in the console that JVM puts the instances of the client classes in EventQueue.
I want that updation should take place in every JTextArea of each client's instance.Can somebody help me to achieve this ?
Client Code
import java.io.*;
import java.net.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
class TestClient88 implements ActionListener
{
Socket s;
DataOutputStream dout;DataInputStream din;BufferedReader br;
static String nameOfClient=null;
static String message=null;
JFrame frame;
JTextArea textArea;
JTextField textField;
JButton button;
public TestClient88 ()
{ //just at the time of login
System.out.println("enter ur name");
nameOfClient=new Scanner(System.in).nextLine();
frame=new JFrame(nameOfClient);
textArea=new JTextArea();
textArea.setBounds(0,0,500,400);
textArea.setEditable(false);
textField=new JTextField();
textField.setBounds(0,405,350,30);
// textField.setText("test");
button=new JButton("send");
button.setBounds(355,405,100,30);
// button.addActionListener(this);
button.addActionListener(this);
frame.add(textField);
frame.add(textArea);
frame.add(button);
frame.setSize(500,500);
frame.setLayout(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try{
s=new Socket("localhost",10);
System.out.println(s);
din=new DataInputStream(s.getInputStream());
dout=new DataOutputStream(s.getOutputStream());
br=new BufferedReader(new InputStreamReader(System.in));//to put the name of client in the server socket
}catch(Exception e){}
}
public void actionPerformed(ActionEvent ae)
{
message=textField.getText();
System.out.println("message is "+message);
textField.setText("");
try{
clientchat();
}catch(Exception e){}
}
public void clientchat() throws IOException
{ // //receiving thread to receive message from server
System.out.println("after start "+Thread.currentThread().getName()); //Main thread
String s1=null;
s1=message;
System.out.println("s1 is "+s1);
try{
dout.writeUTF(nameOfClient+" : " +s1);
message=null;
dout.flush();
// Thread.sleep(20000);
String s2=din.readUTF();
System.out.println("message sent from server is "+ s2);
textArea.append(s2+"\n");
}catch(Exception e){}
}
public static void main(String ar[])
{
new TestClient88();
}
}
Server Code
import java.io.*;
import java.net.*;
import java.util.*;
public class Myserver1
{
ArrayList al=new ArrayList();ServerSocket ss;Socket s;
// static ArrayList clientsList=new ArrayList();
static int count;
ObjectInputStream oin;
public Myserver1()
{
try{
ss=new ServerSocket(10);
System.out.println("server socket is "+ss);
while(true)
{
s=ss.accept();//waits for the client socket
System.out.println("client connected");
System.out.println("mike testing");
al.add(s);
Iterator i=al.iterator();
while(i.hasNext())
{
System.out.println("inside while");
System.out.println(i.next());
}
System.out.println("startting server thread ");
Runnable r=new MyThread(s,al);
Thread t=new Thread(r);
t.start();
}
}catch(Exception e){}
}
public static void main(String ar[])
{
new Myserver1();
}
}
class MyThread implements Runnable
{
Socket s;ArrayList al;
MyThread(Socket s,ArrayList al)
{
this.s=s;
this.al=al;
}
public void run()
{
String s1;int i=0;
try{
DataInputStream din=new DataInputStream(s.getInputStream());
do{
s1=din.readUTF();//message of each client
System.out.println(s1);
if(!s1.equals("stop"))
{
tellEveryone(s1);
}
else
{
DataOutputStream dout=new DataOutputStream(s.getOutputStream());
dout.writeUTF(s1);
dout.flush();
al.remove(s);//logging out a client from the server.
}
}while(!s1.equals("stop"));
}catch(Exception e){}
}
public void tellEveryone(String s1)
{
Iterator i=al.iterator();
while(i.hasNext())
{
try{
Socket sc=(Socket)i.next();
DataOutputStream dout=new DataOutputStream(sc.getOutputStream());
dout.writeUTF(s1);
dout.flush();
// System.out.println("client");
}catch(Exception e){}
}
}
}

Java chat room UI blank and unresponsive

I have followed the newboston tutorials and made a chatroom with server side code and client side code. I wanted to build them together in one app.
My issue is that the client is blank, I used the standalone server from the tutorial.
picture of server chat working with the client chat being a blank window
But if I close the server first, all of the chat appears on the client chat, as in it is all instantly updated.
client chat updated, all previous chats messages displayed.
Standalone server:
package instantmessage;
import javax.swing.JFrame;
public class ServerChatroom {
public static void main(String[] args) {
Server runServer = new Server();
runServer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
runServer.startServer();
}
}
package instantmessage;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Server extends JFrame{
private JTextField userText; //where you type in message
private JTextArea chatWindow; //displays the conversation
private ObjectOutputStream output; //information sent to the recipent
private ObjectInputStream input; //information being received from the recipent
private ServerSocket server;
private Socket connection; //the connection between you and the recipent's computer
//setting up GUI.
public Server(){
super("Instant Messanger - Server"); //the piece in the brackets is the title off the app.
userText = new JTextField();
userText.setEditable(false);//without having a connection you can't send messages.
userText.addActionListener(
new ActionListener(){
#Override
public void actionPerformed(ActionEvent event){
sendMessage(event.getActionCommand()); //sends string that was typed into text field.
userText.setText(""); //after text has been sent, remove the previous message sent.
}
}
);
add(userText, BorderLayout.NORTH); //add userText to GUI, make chat window top of the screen.
chatWindow = new JTextArea();
add(new JScrollPane(chatWindow)); //scrolling pane created for all the chats.
setSize(450,200);
setVisible(true);
}
//create the server and run the serve.
public void startServer(){
try{
server = new ServerSocket(6789, 100); //Server socket. first one the server socket, the second how many clients can wait for connection.
while(true){//the loop should run forever. The main program.
try{//connect and allow conversation with another
waitForConnection();//wait for someone to connect with server.
setupStream(); //create the connection between another computer.
whileChatting(); //allow messages to be sent back and forth during chat.
}catch(EOFException eofException){ //whenever the conversation is ended.
showMessage("\n Server overloaded, connection terminated by the server.");
}finally{
closeServer();
}
}
}catch(IOException ioException){
ioException.printStackTrace();
}
}
//wait for connection, after connection established display connection details.
private void waitForConnection() throws IOException{
showMessage("Waiting for connection to be established...\n"); //so user has something to see, knows program isn't frozen.
connection = server.accept(); //accept the connection.
showMessage("Connection established with " + connection.getInetAddress().getHostName());
}
//gets stream for send/receiving of data.
private void setupStream() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream()); //create pathway for connection to other computer.
output.flush(); //good practice. Cleans up data that was "left over"
input = new ObjectInputStream(connection.getInputStream()); //creates pathway to receive data from other PC.
//no flush for input, the other side has to flash.
showMessage("Connection now active");
}
//sending text back and forth
//this receives the data from the connected computer and displays it.
private void whileChatting() throws IOException{
String message = " You are now connected ";
sendMessage(message);
ableToType(true);
do{//have conversation while client doesn't send CLIENT - END.
try{
message = (String) input.readObject(); //read whatever message is incoming.
showMessage("\n" + message);
}catch(ClassNotFoundException classNotFoundException){
showMessage("\n user has sent garbage.");
}
}while(!message.equals("CLIENT - END"));
}
//close streams/sockets after chat ends. "Good housekeeping". Frees up memory.
private void closeServer(){
showMessage("\n\tTerminating connection...");
ableToType(false);
try{
input.close(); //terminate stream from
output.close(); //terminate stream to
connection.close(); //terminate connection
}catch(IOException ioException){
ioException.printStackTrace();
}
}
//send message to connected computer.
private void sendMessage(String message){
try{
output.writeObject("SERVER - " + message); //creates an object of message and sends it along the output stream.
output.flush(); //remove once it's finished sending.
showMessage("\nSERVER - " + message);
}catch(IOException ioException){
chatWindow.append("\n error sending message"); //print out the error in the chat window that the message was not sent.
}
}
//shows messages on main chat area. Updates the chatWindow so it is always current.
private void showMessage(final String string){
SwingUtilities.invokeLater( //creates thread that updates parts of the GUI.
new Runnable(){
public void run(){
chatWindow.append(string);
}
}
);
}
//sets the textfield editable so that the user can type in it
private void ableToType(final boolean bool){
SwingUtilities.invokeLater( //creates thread that updates parts of the GUI.
new Runnable(){
public void run(){
userText.setEditable(bool);
}
}
);
}
}
My code for the standalone piece:
package chatroomomni;
import javax.swing.JFrame;
public class ChatRoomOmni {
public static void main(String[] args) {
MainMenu runProgram = new MainMenu();
runProgram.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
package chatroomomni;
//the user has to chose to be a client or a server.
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
//layout: first button is host server, second line is a JTextLabel telling user to enter server IP, JTextField next to it for server IP, connect button next.
public class MainMenu extends JFrame{
private JButton hostServer = new JButton("Host server");
private JLabel labelEnterServerIP = new JLabel("Enter Server IP: ");
private JTextField serverIPInput = new JTextField(25);
private JButton connectServer = new JButton("Connect to server");
//constructor
public MainMenu(){
super("Instant Messenger - Main Menu");
serverIPInput.setEditable(true);
//action listener for the host server.
hostServer.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
Server runServer = new Server();
runServer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
CloseFrame();
runServer.startServer();
}
});
//action listener for connect to server.
connectServer.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
if(!String.valueOf(serverIPInput.getText()).equals("")){
System.out.println(String.valueOf(serverIPInput.getText()));
Client client = new Client(String.valueOf(serverIPInput.getText()));
client.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
CloseFrame();
client.startClient();
}
}
});
setLayout(new FlowLayout());
//add items to frame.
add(hostServer);
add(labelEnterServerIP);
add(serverIPInput);
add(connectServer);
setSize(1000, 500);
setVisible(true);
}
public void CloseFrame(){
super.dispose();
}
}
package chatroomomni;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Client extends JFrame{
private JTextField userText; //where you type in message
private JTextArea chatWindow; //displays the conversation
private ObjectOutputStream output; //information sent to the recipent
private ObjectInputStream input; //information being received from the recipent
private Socket connection; //the connection between you and the recipent's computer
private String message;
private String serverIP;
public Client(String host){
super("Instant Messenger - 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.NORTH);
chatWindow = new JTextArea();
add(new JScrollPane(chatWindow), BorderLayout.CENTER);
setSize(500, 400);
setVisible(true);
}
//connect to the server,
public void startClient(){
try{
connectToServer();
setupStream();
whileChatting();
}catch(EOFException eofException){
showMessage("\n Client terminated the connection");
}catch(IOException ioException){
ioException.printStackTrace();
}finally{
closeClient();
}
}
private void connectToServer() throws IOException{
showMessage("Attempting to connect to server...\n");
connection = new Socket(InetAddress.getByName(serverIP), 6789);
showMessage("Connection established to: " + connection.getInetAddress().getHostAddress());
}
private void setupStream() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream()); //create pathway for connection to other computer.
output.flush(); //good practice. Cleans up data that was "left over"
input = new ObjectInputStream(connection.getInputStream()); //creates pathway to receive data from other PC.
//no flush for input, the other side has to flash.
showMessage("Connection now active");
}
private void whileChatting() throws IOException{
String message = " You are now connected ";
sendMessage(message);
ableToType(true);
do{//have conversation while server doesn't send SERVER - END.
try{
message = (String) input.readObject(); //read whatever message is incoming.
showMessage("\n" + message);
}catch(ClassNotFoundException classNotFoundException){
showMessage("\n server has sent garbage.");
}
}while(!message.equals("SERVER - END") || !message.equals("SERVER - TERMINATE CONNECTION"));
}
private void closeClient(){
showMessage("\n\tTerminating connection...");
ableToType(false);
try{
input.close(); //terminate stream from
output.close(); //terminate stream to
connection.close(); //terminate connection
}catch(IOException ioException){
ioException.printStackTrace();
}
}
private void sendMessage(final String message){
try{
output.writeObject("CLIENT - " + message); //creates an object of message and sends it along the output stream.
output.flush(); //remove once it's finished sending.
showMessage("\nCLIENT - " + message);
}catch(IOException ioException){
chatWindow.append("\n error sending message"); //print out the error in the chat window that the message was not sent.
}
}
private void showMessage(final String string){
SwingUtilities.invokeLater( //creates thread that updates parts of the GUI.
new Runnable(){
public void run(){
chatWindow.append(string);
}
}
);
}
private void ableToType(final boolean bool){
SwingUtilities.invokeLater( //creates thread that updates parts of the GUI.
new Runnable(){
public void run(){
userText.setEditable(bool);
}
}
);
}
}
package chatroomomni;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Server extends JFrame{
private JTextField userText; //where you type in message
private JTextArea chatWindow; //displays the conversation
private ObjectOutputStream output; //information sent to the recipent
private ObjectInputStream input; //information being received from the recipent
private ServerSocket server;
private Socket connection; //the connection between you and the recipent's computer
//setting up GUI.
public Server(){
super("Instant Messanger - Server"); //the piece in the brackets is the title off the app.
userText = new JTextField();
userText.setEditable(false);//without having a connection you can't send messages.
userText.addActionListener(
new ActionListener(){
#Override
public void actionPerformed(ActionEvent event){
sendMessage(event.getActionCommand()); //sends string that was typed into text field.
userText.setText(""); //after text has been sent, remove the previous message sent.
}
}
);
add(userText, BorderLayout.NORTH); //add userText to GUI, make chat window top of the screen.
chatWindow = new JTextArea();
add(new JScrollPane(chatWindow)); //scrolling pane created for all the chats.
setSize(450,200);
setVisible(true);
}
//create the server and run the serve.
public void startServer(){
try{
server = new ServerSocket(6789, 100); //Server socket. first one the server socket, the second how many clients can wait for connection.
while(true){//the loop should run forever. The main program.
try{//connect and allow conversation with another
waitForConnection();//wait for someone to connect with server.
setupStream(); //create the connection between another computer.
whileChatting(); //allow messages to be sent back and forth during chat.
}catch(EOFException eofException){ //whenever the conversation is ended.
showMessage("\n Server overloaded, connection terminated by the server.");
}finally{
closeServer();
}
}
}catch(IOException ioException){
ioException.printStackTrace();
}
}
//wait for connection, after connection established display connection details.
private void waitForConnection() throws IOException{
showMessage("Waiting for connection to be established...\n"); //so user has something to see, knows program isn't frozen.
connection = server.accept(); //accept the connection.
showMessage("Connection established with " + connection.getInetAddress().getHostName());
}
//gets stream for send/receiving of data.
private void setupStream() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream()); //create pathway for connection to other computer.
output.flush(); //good practice. Cleans up data that was "left over"
input = new ObjectInputStream(connection.getInputStream()); //creates pathway to receive data from other PC.
//no flush for input, the other side has to flash.
showMessage("Connection now active");
}
//sending text back and forth
//this receives the data from the connected computer and displays it.
private void whileChatting() throws IOException{
String message = " You are now connected ";
sendMessage(message);
ableToType(true);
do{//have conversation while client doesn't send CLIENT - END.
try{
message = (String) input.readObject(); //read whatever message is incoming.
showMessage("\n" + message);
}catch(ClassNotFoundException classNotFoundException){
showMessage("\n user has sent garbage.");
}
}while(!message.equals("CLIENT - END"));
}
//close streams/sockets after chat ends. "Good housekeeping". Frees up memory.
private void closeServer(){
showMessage("\n\tTerminating connection...");
ableToType(false);
try{
input.close(); //terminate stream from
output.close(); //terminate stream to
connection.close(); //terminate connection
}catch(IOException ioException){
ioException.printStackTrace();
}
}
//send message to connected computer.
private void sendMessage(String message){
try{
output.writeObject("SERVER - " + message); //creates an object of message and sends it along the output stream.
output.flush(); //remove once it's finished sending.
showMessage("\nSERVER - " + message);
}catch(IOException ioException){
chatWindow.append("\n error sending message"); //print out the error in the chat window that the message was not sent.
}
}
//shows messages on main chat area. Updates the chatWindow so it is always current.
private void showMessage(final String string){
SwingUtilities.invokeLater( //creates thread that updates parts of the GUI.
new Runnable(){
public void run(){
chatWindow.append(string);
}
}
);
}
//sets the textfield editable so that the user can type in it
private void ableToType(final boolean bool){
SwingUtilities.invokeLater( //creates thread that updates parts of the GUI.
new Runnable(){
public void run(){
userText.setEditable(bool);
}
}
);
}
}
All the netbeans project files uploaded to zippyshare: www116(dot)zippyshare(dot)com/v/qAa5BGWn/file(dot)html (not allowed to post more than 2 links, I apologize for trying to circumvent the rule but it is relevant)
Any help would be appreciated.

How to build a multithreading socket server

I try to build server that could talk with several clients at the same time.
But there are some problems with the thread, and the code doesn't work well.
Could you tell me what is wrong with the thread part? Thank you very much.
public class ServerMulti extends JFrame implements ActionListener{
private static final int PORT = 60534;
private JTextField textField = new JTextField();
private static JTextArea textArea = new JTextArea();
private JButton button = new JButton();
public static ServerSocket server;
public static Socket socket;
public static BufferedReader in;
public static PrintWriter out;
public ServerMulti(){
/*
* build up GUI
*/
setTitle("Server Multi");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300,400);
setBackground(Color.white);
setLayout(new BorderLayout());
button.setText("Send");
button.setSize(300, 50);
textField.setText("Type here");
textArea.setSize(300, 50);
add(textField, BorderLayout.NORTH);
add(new JScrollPane(textArea), BorderLayout.CENTER);
add(button, BorderLayout.SOUTH);
setLocation(300, 100);
button.addActionListener(this);
setVisible(true);
}
/*
* print out the information that need to sent to clients
*
*/
public void actionPerformed(ActionEvent e) {
textArea.append(textField.getText()+"\n");
out.println(textField.getText());
textField.setText("");
}
public static void main(String[] args) throws IOException{
new ServerMulti();
//build up the socket and server
try{
server = new ServerSocket(PORT);
socket = server.accept();
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream());
textArea.append("Connected. "+" Port: " + PORT + "\n");
while(true){
worker w = new worker();
Thread t = new Thread(w);
t.start();
}
}catch (IOException e) {
System.out.println("Accept failed:" +PORT);
System.exit(-1);
}
}
//to the same server, different sockets are created connecting to different client
public static class worker implements Runnable{
public void run() {
String msg;
/*
* the "in.readLine()" give the data only once
* 1. so we save the information to a String from the socket
* 2. Then sent out a feedback to client, through socket
* 3. print out the String we just collected
*/
while(true){
try {
msg = in.readLine();
out.println("Server received : " + msg);
textArea.append(msg+"\n");
} catch (IOException e) {
System.out.println("Fail");
e.printStackTrace();
}
}
}
}
}
There are a couple of problems with this, but in terms of multithreading the server: ServerSocket.accept() blocks until a new client attempts to connect. In your code this only happens once; so only one client will be accepted. The layout should instead be something like this:
ServerSocket ss = new ServerSocket(PORT);
while (LISTENING) {
Socket sock = ss.accept();
Handler handler = new Handler(sock);
new Thread(handler).start();
//With the LISTENING variable dealt with as well
}
Here the class Handler should be a Runnable class that deals with the socket on another thread. The while loop can then go back and accept a new connection.

UDP Chatting Problem

hello friends i have created a UDP chatting program through which the clients can communicate over LAN.
I have created a genaralized program i.e. I run the same code with different port nos. and IP address when on LAN
My problem is that This code below works fine on localhost but when i try to connect two machines this code doesnt work..there is no error as of such but still the two clients cant communicate
I have also switched off the firewalls.But i am unable to find out why i cant communicate between two machines
The Code is as follows ::
import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
class ChatApplDG extends Frame implements ActionListener
{
TextField tf = new TextField(50);
Button btn = new Button("Send");
Button exit = new Button("Exit");
TextArea ta = new TextArea(50,10);
int fromPort, toPort;
String hostName;
DatagramSocket dgSock;
public static void main(String args[]) throws Exception
{
ChatApplDG ca = new ChatApplDG();
ca.startClient(args[0],Integer.parseInt(args[1]),Integer.parseInt(args[2]));
}
ChatApplDG()
{
Panel p = new Panel();
add(p,BorderLayout.NORTH);
p.add(tf);
p.add(btn);
p.add(exit);
add(ta,BorderLayout.CENTER);
btn.addActionListener(this);
exit.addActionListener(this);
setSize(500,300);
show();
ta.setEditable(false);
}
void startClient(String hName,int fPort,int tPort)
{
try
{
hostName = hName;
fromPort=fPort;
toPort=tPort;
dgSock = new DatagramSocket(fromPort);
ta.append("Ready To Send ...\n");
RunningThreadDG rt = new RunningThreadDG(dgSock,ta);
Thread thread = new Thread(rt);
thread.start();
}
catch(Exception e)
{
}
}
public void actionPerformed(ActionEvent ae)
{
if(ae.getSource()==btn)
{
try
{
byte buff[] = new byte[500];
InetAddress remoteHost = InetAddress.getByName(hostName);
buff=tf.getText().getBytes();
dgSock.send(new DatagramPacket(buff,buff.length,remoteHost.getLocalHost(),toPort));
ta.append("Send : " + tf.getText() + "\n");
tf.setText("");
}
catch(Exception e)
{
}
}
else
{
System.exit(0);
}
}
}
class RunningThreadDG extends Frame implements Runnable
{
DatagramSocket dgSock;
TextArea ta;
String str;
RunningThreadDG(DatagramSocket dgs,TextArea t)
{
dgSock=dgs;
ta=t;
}
public void run()
{
byte[] buff = new byte[500];
while(true)
{
try
{
DatagramPacket dgPack = new DatagramPacket(buff,buff.length);
dgSock.receive(dgPack);
ta.append("Received : " + new String(dgPack.getData(),0,dgPack.getLength()) + "\n");
}
catch(Exception e)
{
}
}
}
}
Here's a problem:
dgSock.send(new DatagramPacket(buff,buff.length,remoteHost.getLocalHost(),toPort));
remoteHost.getLocalHost() returns an InetAddress for your local host. Try just passing remoteHost instead of remoteHost.getLocalHost():
dgSock.send(new DatagramPacket(buff,buff.length,remoteHost,toPort));
In addtion to echo's answer I would like to add that you should at least add e.printStackTrace(); to your catch blocks.
Also check whether both machines can resolve each others hostnames by calling nslookup hostname. Or just ping hostname from each machine.

Categories