1

I'm working on the client side application of the client/server chat I'm doing for learning experience. My problem is I can't seem to get the socket and swing,both to run at the same time.

What I want to is, when the user opens a JOpionsPane and enters the hostname and port number, clicks okay, then they are connected. When the socket information was hardcoded it worked fine, but now I'm trying to get the users input for it.

What's meant to happen is, action listener is supposed to create the new SocketManager object that handles communication. Event though it says it's connected, it doesn't run. When I create the new SocketManager object and run it on a new thread it connects and revives messages form the server, but then the swings freezes and I have to end the process to shut it down.

Should I start it on a new worker thread or something? Maybe it's just because I'm tired, but I'm out of ideas.

EDIT I updated my ActLis.class and SocketManager.class with the suggestion of adding a new thread for my SocketManager object 'network'. When I try and use 'network' though it returns null for some reason.

ActLis.clss

package com.client.core;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;

public class ActLis implements ActionListener {

private Main main = new Main();;
private JTextField ipadress = new JTextField(),
        portnumber = new JTextField(),
        actionField;

private String username;

final JComponent[] ipinp = new JComponent[]{new JLabel("Enter Hostname (IP Adress): "),
        ipadress,
        new JLabel("Enter Port number: "), portnumber};
private SocketManager network;
private Window win;

public ActLis(){

}

public ActLis(JTextField t, Window w){
    actionField = t;
    win = w;

}

@Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();


if(cmd == "Exit"){
    System.exit(0);
} else if(cmd == "Connect to IP"){
    try{
        JOptionPane.showMessageDialog(null, ipinp, "Connect to IP", JOptionPane.PLAIN_MESSAGE);
        if(network != null){
            network.close();
        }
        network = new SocketManager(ipadress.getText(),Integer.parseInt(portnumber.getText()));
        network.setGUI(win);
        Thread t = new Thread(network);
        t.start();
        JOptionPane.showMessageDialog(null, "Connected to chat host successfully!","Connected", JOptionPane.INFORMATION_MESSAGE);
    }catch(Exception ee){
        JOptionPane.showMessageDialog(null, "Could not connect. Check IP adress or internet connection","Error - Could not connect", JOptionPane.ERROR_MESSAGE);
        ee.printStackTrace();
    }

} else if (cmd == "chatWriter"){

    if( actionField.getText() != ""){   
        try{
            network.send(actionField.getText());
            win.updateChat(actionField.getText());
            actionField.setText("");
            actionField.requestFocus();
        }catch(Exception ex){
            JOptionPane.showMessageDialog(null, "You are not connected to a host. (File -> Connect to IP)","Error - Not Connected", JOptionPane.ERROR_MESSAGE);
            ex.printStackTrace();
        }

    }

} else if (cmd == "setUsername"){
    username = actionField.getText();
    network.send("USERNAME:" + username);


}


}
}

Main.class

package com.client.core;

import javax.swing.JFrame;

public class Main extends JFrame{

private SocketManager network;

public static void main(String[] args){     
    Main main = new Main();
    main.run();

}

private void run(){
    Window win = new Window();
    win.setVisible(true);
}
}

SocketManager.class

package com.client.core;

import java.io.*;
import java.net.*;

public class SocketManager implements Runnable {

private Socket sock;
private PrintWriter output;
private BufferedReader input;
private String hostname;
private int portnumber;
private String message;
private Window gui;

public SocketManager(String ip, int port){
    try{
        hostname = ip;
        portnumber = port;
    }catch(Exception e){
        System.out.println("Client: Socket failed to connect.");
    }
}



public synchronized void send(String data){
    try{
        //System.out.println("Attempting to send: " + data);
        output.println(data);
        output.flush();
        //System.out.println("Message sent.");
    }catch(Exception e){
        System.out.println("Message could not send.");
    }
}

public synchronized void setGUI(Window w){
    gui = w;
}

public synchronized void connect(){
    try{
        sock = new Socket(hostname,portnumber);
    }catch(Exception e){

    }
}

public synchronized Socket getSocket(){
    return sock;
}

public synchronized void setSocket(SocketManager s){
    sock = s.getSocket();
}

public synchronized void close(){
    try{
        sock.close();
    }catch(Exception e){
        System.out.println("Could not close connection.");
    }
    output = null;
    input = null;
    System.gc();
}

public synchronized boolean isConnected(){
    return (sock == null) ? false : (sock.isConnected() && !sock.isClosed());
}

public synchronized void listenStream(){
    try {
        while((message = input.readLine()) != null){        
            System.out.println("Server: " + message);
            gui.updateChat(message);
        }
    } catch (Exception e) {

    }
}

@Override
public void run() {
    try {
        sock = new Socket(hostname,portnumber);
        output = new PrintWriter(sock.getOutputStream(),true);
        input = new BufferedReader(
                new InputStreamReader(sock.getInputStream()));
        while(true){
            listenStream();
        }
    } catch (Exception e) {
        System.out.println("Run method fail. -> SocketManager.run()");
    }finally{
        try {
            sock.close();
        } catch (Exception e) {

        }
    }

}

}

Window.class

package com.client.core;

import java.awt.*;
import javax.swing.*;


public class Window extends JFrame{

private int screenWidth = 800;
private int screenHeight = 600;

private SocketManager network;

private JPanel window = new JPanel(new BorderLayout()),
        center = new JPanel(new BorderLayout()),
        right = new JPanel(new BorderLayout()),
        display = new JPanel( new BorderLayout()),
        chat = new JPanel(),
        users = new JPanel(new BorderLayout());

private JTextArea chatBox = new JTextArea("Welcome to the chat!", 7,50),
        listOfUsers = new JTextArea("None Online");

private JTextField chatWrite = new JTextField(),
        userSearch = new JTextField(10),
        username = new JTextField();

private JScrollPane userList = new JScrollPane(listOfUsers),
        currentChat = new JScrollPane(chatBox);

private JMenuBar menu = new JMenuBar();

private JMenu file = new JMenu("File");

private JMenuItem exit = new JMenuItem("Exit"),
        ipconnect = new JMenuItem("Connect to IP");
private JComponent[] login = new JComponent[]{new JLabel("Username:"), username};

public Window(){

    //Initial Setup
    super("NAMEHERE - Chat Client Alpha v0.0.1");
    setResizable(true);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(screenWidth,screenHeight);


    //Panels
    listOfUsers.setLineWrap(true);
    listOfUsers.setEditable(false);
    display.setBackground(Color.black);
    chat.setLayout(new BoxLayout(chat, BoxLayout.Y_AXIS));
    chat.setBackground(Color.blue);
    users.setBackground(Color.green);       

    //TextFields
    addChatArea();

    //Menu bar
    addMenuBar();   

    //Adding the main panels. 
    addPanels();

    //Listeners
    addListeners();

    for(int x = 0; x < 1; x++){
        login();
    }
}

private void login(){
    JOptionPane.showMessageDialog(null, login, "Log in", JOptionPane.PLAIN_MESSAGE);
}

private void addChatArea(){
    chatBox.setEditable(false);     
    userList.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    currentChat.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    users.add(userList);
    users.add(userSearch, BorderLayout.NORTH);
    chat.add(currentChat);
    chat.add(chatWrite);
    chat.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
}

private void addMenuBar(){
    file.add(ipconnect);
    file.add(exit);
    menu.add(file); 
}

private void addPanels(){
    right.add(users);
    center.add(display, BorderLayout.CENTER);
    center.add(chat, BorderLayout.SOUTH);
    window.add(center, BorderLayout.CENTER);
    window.add(right, BorderLayout.EAST);
    window.add(menu, BorderLayout.NORTH);
    add(window);
}

private void addListeners(){
    username.addActionListener(new ActLis(username, this));
    chatWrite.addActionListener(new ActLis(chatWrite, this));
    username.setActionCommand("setUsername");
    chatWrite.setActionCommand("chatWriter");
    ipconnect.addActionListener(new ActLis());
    exit.addActionListener(new ActLis());
}

public void setNetwork(SocketManager n){
    network = n;
}

public void updateChat(String s){
    chatBox.setText(chatBox.getText() + "\n" + s);
}

}
cgasser
  • 603
  • 2
  • 11
  • 24
  • And how are we supposed to help with this code ? The only code that I recognize are some updates of Swing components and showing some message dialogs. All other code is your custom code which we do not know – Robin May 15 '12 at 05:51
  • @Robin I apologies, I'll post all my code. I'm very tired was getting frustrated. – cgasser May 15 '12 at 05:54
  • 3
    See also this related [example](http://stackoverflow.com/a/3245805/230513). – trashgod May 15 '12 at 06:08
  • @trashgod Thank you for the link. I actually read that yesterday when trying to solve another socket problem. I'm knew to them. – cgasser May 15 '12 at 06:18
  • 1
    Maybe also take a look at the SwingWorker class – keuleJ May 15 '12 at 06:33
  • @keuleJ I have done this as well, thanks for the suggestion. Would you recommend I do that maybe instead of just starting it in a normal thread? – cgasser May 15 '12 at 06:37
  • @Zexanima : The best and easy way I can think of is, instead of using `showMessageDialog(...)`, you can use a `showInputDialog(...)`, that might can halt your control proceedings till you won't enter any value, AFAIK, I hope I am right in saying this :-) – nIcE cOw May 15 '12 at 12:29
  • @nIcEcOw Well I got it to work by starting a new thread for my network object in ActList. But even after I set it, it still says it's null when I try and use it. – cgasser May 15 '12 at 17:55
  • 1
    Do remember though, If you will click on Cancel Button on JOptionPane with showInputDialog() or you will close it from the Red X Button, both ways you will get one null value. – nIcE cOw May 15 '12 at 18:01
  • @nIcEcOw I didn't know that, thanks! However, I am getting the correct input from it because my sockets connect and I am able to send messages from the server and the client receives them. My problem is when I set up the new socket in 'ActLis', the 'SocketManager' object there 'network' is still null when I try and use it for some reason even though I set it and it's working for incoming messages. – cgasser May 15 '12 at 18:31
  • 1
    @Zexanima Remember that SwingComponents should be accessed only in the EventDispatchThread. SwingWorker makes this easier. Do your I/O work in the doInBackground() and the rest in the EDT. But you can also do this with normal Threads and lot's of SwingUtilities.invokeLater()... – keuleJ May 15 '12 at 19:29
  • @keuleJ I know, but I don't think using a SwingWorker will solve the problem of that SocketManger object being null even though I assigned it and it's working. My code is horribly done anyway, so I'm going to have to have to start over. Thanks a ton for your help though! – cgasser May 15 '12 at 19:41

1 Answers1

1

Ok @Zexanima you have create a Socket class for socket manager. Something like this:

public class YouSocketClass {
   static public Socket socket = null;
   static public InputStream in = null;
   static public OutputStream out = null;

   public YouSocketClass() {
     super();
   }
   public static final Socket getConnection(final String ip, final int port, final int timeout) {
    try {
        socket = new Socket(ip, port);
        try {
            socket.setSoTimeout(timeout);
        } catch(SocketException se) {
            log("Server Timeout");
        }
        in = socket.getInputStream();
        out = socket.getOutputStream();
    } catch(ConnectException e) {
        log("Server name or server ip is failed. " + e.getMessage());
        e.printStackTrace();
    } catch(Exception e) {
        log("ERROR Socket: " + e.getMessage() + " " + e.getCause());
        e.printStackTrace();
    }
    return socket;
}

public static void closeConnection() {
    try {
        if(socket != null) {
            if(in != null) {
                if(out != null) {
                    socket.close();
                    in.close();
                    out.close();
                }
            }
        }
    } catch(Exception e2) {
        e2.printStackTrace();
    }
}

private static Object log(Object sms) {
    System.out.println("Test Socket1.0: " + sms);
    return sms;
}
}

I hope that serve. :)

hekomobile
  • 1,388
  • 1
  • 14
  • 35
  • I edited my post and added my SocketManager class. I know my code in it is really messy, but isn't that basicly what it is? Or are you saying I need this along with my SocketManager class? – cgasser May 15 '12 at 06:05
  • Ok @Zexamina. All you need is to implement this simple class and make requests to the server from your main class, calling the **YouSocketSocket** class. It's simple, complications do not see your program. – hekomobile May 15 '12 at 06:13
  • That will mean I'll have to rework a lot of the code, so I'll have to try it tomorrow when I'm less drowsy and less prone to make a mistake. Thank you for the help. :) – cgasser May 15 '12 at 06:27