Question

I am trying to create a server and client(s) app, where the server can send messages to the client(s), and the client(s) can only accept the messages from the server.

I have succeed this goal. The problem is, that the client.jar won't receive any messages from the server. But everything work just fine in netbean.

Any idea why this happen ?

Here's my complete server code :

public sServerUI() {
    super("Server : "+System.getenv("COMPUTERNAME")); // mendapatkan nama komputer
    initComponents();
}

public void startListener(){    
    Random randomGen = new Random();
    try{
        myPort = randomGen.nextInt(9999);
        server = new ServerSocket(myPort);//Bebas portnya, tp nggk boleh sudah terpakai atau pakai random jg bisa
        btnListen.setEnabled(false);
        while(key == null) {
            key = JOptionPane.showInputDialog(this, "Input your Key : ", "Insert Key", JOptionPane.PLAIN_MESSAGE);
        }
        if(key.equals("")) {
            key = "Random";
            txtMessage.setText(txtMessage.getText()+"Invalid key inputted, key automatically set to '"+key+"'\n");
        } else txtMessage.setText(txtMessage.getText()+"Key set to '"+key+"'\n");
    } catch (IOException e) {//Kalau sudah terpakai muncul error
        JOptionPane.showMessageDialog(this, "Could not listen at " + myPort);
        //Gagal, keluarin info
    } finally{
        myPort = server.getLocalPort();
        lblPort.setText("Port: "+myPort);
        System.out.println("Port: "+myPort);
    }

    acceptClient.start();
}
public void windowClosing(WindowEvent e){
    try {
        server.close();
        for (int i=0;i<numberOfClient;i++){
            socketIn[i].close();
            socketOut[i].close();
        }
    } catch (IOException ex) {
        System.out.println("Error "+ex.getMessage());
    }
}

class Accepter extends Thread{
    @Override
    public void run(){
        while (true){
            try{
                client[numberOfClient] = server.accept();
                numberOfClient++;
                lblStatus.setText("Status: "+numberOfClient+" client(s) connected");

                Handler handleClient = new Handler(numberOfClient-1);
                handleClient.start();
            } catch (IOException e) {
                JOptionPane.showMessageDialog(null, "Accept failed: " + myPort);
            }
        }
    }
}
class Handler extends Thread{
    private int arr;
    Handler(int ar){
        arr = ar;
        try{
            socketIn[arr] = new BufferedReader(new InputStreamReader(client[arr].getInputStream()));
            socketOut[arr] = new PrintWriter(client[arr].getOutputStream(), true);
        } catch (IOException e) {
            JOptionPane.showMessageDialog(null, "Read failed");
        }
    }

    @Override
    public void run(){
        while (true){
            try{
                if (socketIn[arr].ready()){
                    System.out.println("Reading...");
                    line = socketIn[arr].readLine();
                    if (!txtMessage.getText().equals("")){
                        txtMessage.setText(txtMessage.getText()+"\n");
                        //broadcast message ke client2 lain
                    }
                    txtMessage.setText(txtMessage.getText()+"Client "+(arr+1)+": "+line);

                    for (int i=0;i<numberOfClient;i++){
                        if (i!=arr){//jgn kembaliin ke client yg kirim
                            socketOut[i].println("Client "+(arr+1)+": "+line);
                        }
                    }
                }
            } catch (IOException e) {
                System.out.println("Read failed");
            }
        }
    }
}
private void btnListenActionPerformed(java.awt.event.ActionEvent evt) {                                          
    // TODO add your handling code here:
    startListener();
}
private void sendData(String data) {
    for (int j=0;j<numberOfClient;j++){
        socketOut[j].println(data);
    } 
}

private void btnSendActionPerformed(java.awt.event.ActionEvent evt) {                                        
    // TODO add your handling code here:
    if(numberOfClient > 0) {
        int packetIndex = 1;
        String ext = getExt(filePath, '.');
        String sData = "start"+pemisahString+fByte.length+pemisahString+ext+pemisahString; //menaruh kata kunci 'start' dan ukuran file di awal message, serta extensionnya
        sendData(sData);
        sData = "";
        int k = 0;
        for(int i = 0; i < fByte.length; i++) {
            if(k >= Math.ceil((double)fByte.length/10.0)) {
                k = 0;
                sData = rc4(key, sData);
                sendData(Integer.toString(packetIndex)+pemisahString+sData);
                txtMessage.setText(txtMessage.getText()+"packet-"+packetIndex+" sent ! isi : "+revertToString(rc4(key,revertToString(sData)))+"\n");
                packetIndex++;
                sData = "";
            }
            sData += fByte[i];
            sData += pemisahString;
            k++;
            if(i == fByte.length-1) {
                sData = rc4(key, sData);
                sendData(Integer.toString(packetIndex)+pemisahString+sData);
                txtMessage.setText(txtMessage.getText()+"packet-"+packetIndex+" sent ! isi : "+revertToString(rc4(key,revertToString(sData)))+"\n");
                packetIndex++;
                sData = "";
            }
        }
        sData = "end"+pemisahString;
        sendData(sData);
        txtMessage.setText(txtMessage.getText() + "Done ! divided into "+k+" piece(s) per packet\n");
    } else JOptionPane.showMessageDialog(this, "No Client Connected !", "Error", JOptionPane.ERROR_MESSAGE);
}                                       

private void fileBtnActionPerformed(java.awt.event.ActionEvent evt) {                                        
    // TODO add your handling code here:
    JFileChooser chooser = new JFileChooser();
    chooser.setCurrentDirectory(new File("d:/Kul/Smstr 6/Kripto n Steno/Stream Cipher/"));
    int returnVal = chooser.showOpenDialog(this);

    if(returnVal == JFileChooser.APPROVE_OPTION) {
        filePath = chooser.getSelectedFile().getPath();
        try {
            inputFile = new File(filePath);
            fIn = new FileInputStream(inputFile);
            fByte = new byte[(int)inputFile.length()];
            System.out.println("file size : "+(int)inputFile.length()+" byte(s)");
            System.out.print("Isi file : ");
            fIn.read(fByte);
            fIn.close();
            for(int i = 0; i < fByte.length; i ++) {
                System.out.print(fByte[i]+" ");
            }
            System.out.print("end of file\n");

            String stringBuatDitampilin = getExt(filePath, (char)92);

            txtMessage.setText(txtMessage.getText() + "'" + stringBuatDitampilin + "' Loaded !\n");
            btnSend.setEnabled(true);
            //fIn.close();
            //JOptionPane.showMessageDialog(this, "File Loaded !", "Success", JOptionPane.INFORMATION_MESSAGE);
        } catch(java.io.IOException e) {
            JOptionPane.showMessageDialog(this, e.toString(), "IO Error", JOptionPane.ERROR_MESSAGE);
        }
    }
}          
public static void main(String args[]) {
    /* Set the Nimbus look and feel */
    //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
    /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
     * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
     */
    try {
        for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                javax.swing.UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
        java.util.logging.Logger.getLogger(sServerUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }
    //</editor-fold>

    /* Create and display the form */
    java.awt.EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            new sServerUI().setVisible(true);
        }
    });
}

and here's my complete client code :

public sClientUI() {
    super("Client");
    initComponents();
}

public void listenSocket(){
//Create socket connection
    try{
        socket = new Socket(txtHost.getText(), Integer.parseInt(txtPort.getText()));
        socketOut = new PrintWriter(socket.getOutputStream(), true);
        socketIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        txtMessage.setText(txtMessage.getText()+"Succesfully connected to "+txtHost.getText()+" !\n");
        while(key == null) {
            key = JOptionPane.showInputDialog(this, "Input your Key : ", "Insert Key", JOptionPane.PLAIN_MESSAGE);
        }
        if(key.equals("")) {
            key = "Random";
            txtMessage.setText(txtMessage.getText()+"Invalid key inputted, key automatically set to '"+key+"'\n");
        } else txtMessage.setText(txtMessage.getText()+"Key set to '"+key+"'\n");
        txtHost.setEditable(false);
        txtPort.setEditable(false);
        btnConnect.setEnabled(false);
        myListener = new Timer(250, readLine);
        myListener.start();
    } catch (UnknownHostException e) {
        JOptionPane.showMessageDialog(this, "Unknown host: "+e.getMessage(), "Unknown Hostname", JOptionPane.ERROR_MESSAGE);
    } catch  (IOException e) {
        JOptionPane.showMessageDialog(this, "Either your hostname is wrong, or you entered wrong port number\n"+e.getMessage(),"Input Error", JOptionPane.ERROR_MESSAGE);
    } catch (NumberFormatException e) {
        JOptionPane.showMessageDialog(this, e.getMessage(),"Invalid Port Number", JOptionPane.ERROR_MESSAGE);
    }
}

public void windowClosing(WindowEvent e){
    try {
        socket.close();
        socketIn.close();
        socketOut.close();
    } catch (IOException ex) {
        System.out.println("Error "+ex.getMessage());
    }
}
ActionListener readLine = new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent ae) {
        try{
            if (socketIn.ready()){
                String tempReceiver;
                if((tempReceiver = socketIn.readLine()) != null) {
                    exStr(tempReceiver); //untuk memotong-motong string dan meng-create file baru
                }
            }
        } catch (IOException e) {
            System.out.println("Read failed");
        }
    }
};
private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {                                           
    // TODO add your handling code here:
    listenSocket();
}   
public static void main(String args[]) {
    /* Set the Nimbus look and feel */
    //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
    /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
     * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
     */
    try {
        for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                javax.swing.UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
        java.util.logging.Logger.getLogger(sClientUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }
    //</editor-fold>

    /* Create and display the form */
    java.awt.EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            new sClientUI().setVisible(true);
        }
    });
}

the .jar client and server has been connected to each other, they just can't send or receive any messages

Was it helpful?

Solution 2

Solved

it was because i encrypt the message using some cipher algorithm and i send the bytes as string some ciphered character are unreadable by the console, and so the program can't do certain key operations to process the message

thanks all anyway :)

OTHER TIPS

Your code is missing some important peaces. For example the imports. They show us what libraries you used and give us chances to do some reserches.

1) For example the line:

myListener = new Timer(250, readLine);

It can't be java.util.Timer because this class doesn't have an constructor (long/int, ActionListener). Possibly this call only runs once instead of multiple times, but I'm unable to know and tell you that.

2) Another example: You have the line

acceptClient.start();

I can only assume that there is an instance variable

Accepter acceptClient = new Accepter();

but it can also refer to a completely different class which works differently.

3) Back to my first example:

You are doing some kind of polling. This is not good style in java because Java Thready are by design optimized for blocking threads. Use a code block like this instead (untested; inspired by your server code)

class ClientThread extends Thread{
    @Override
    public void run(){
        try{
            String tempReceiver;
            while ((tempReceiver = socketIn.readLine()) != null) {
                exStr(tempReceiver);
            }
        } catch (IOException e) {
            System.out.println("Read failed");
        }
    }
}

In this case you don't need polling and you have immediate response. This consumes less CPU. A completely different option would be to use Java NIO, which is more optimized for single-thread applications (or let's call it few-thread).

Some off-topic remarks:

OT 1) Calling Swing-functions like JOptionPane.showMessageDialog() and setText() is dangerous from threads. Swing itself is not Thread-safe. You should use a EventQueue.invokeLater() wrapper around it. my favourite: SwingUtils.invokeLater()

OT 2) Having the variable tempReceiver class-global (I assume this because I can't see any declaration) is also dangerous because you likely use it somewhere else and possibly exactly overwrite it during the readLine() and exStr() calls in the other thread (if Timer is the Swing-implementation, it runs an extra thread).

OT 3) You are saying "the .jar client and server has been connected to each other". Does this mean you have two open console windows with a java -jar command running in each window? If not, you might miss some important console output (possibly exceptions). The windows distribution of java has 2 java runners: javaw.exe which is called when double-clicking a .jar file in the Explorer. And java.exe which also runs your program but also opens a console window which shows the output of System.out.println etc. This console is very important for debugging. It shows the same output as the Debug window in NetBeans or Eclipse.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top