【问题标题】:Java .jar file can't receive socket messageJava .jar 文件无法接收套接字消息
【发布时间】:2014-06-20 18:31:04
【问题描述】:

我正在尝试创建一个服务器和客户端应用程序,其中服务器可以向客户端发送消息,而客户端只能接受来自服务器的消息。

我已经实现了这个目标。问题是,client.jar 不会收到来自服务器的任何消息。但是在 netbean 中一切正常。

知道为什么会这样吗?

这是我完整的服务器代码:

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);
        }
    });
}

这是我完整的客户端代码:

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);
        }
    });
}

.jar 客户端和服务器已经相互连接,它们只是无法发送或接收任何消息

【问题讨论】:

  • 首先要检查的是防火墙配置。也尝试使用 localhost 地址运行服务器和客户端
  • @Tech 我已经设置了 Windows 防火墙(我使用的是 Windows 7),以允许我的应用程序使用网络进行入站和出站规则,但结果仍然相同。抱歉,如果我的下一个问题有点愚蠢,但是您的 localhost 地址是什么意思?是不是像“127.0.0.1”?
  • jar 文件是惰性对象。它不能“接收”任何东西。
  • @Bondle 是的,我就是这个意思。
  • 也许你们中的一些人误认为我想要达到的目标,但问题已经解决了,我已经发布了答案;)还是谢谢

标签: java sockets netbeans jar executable-jar


【解决方案1】:

解决了

这是因为我使用某种密码算法加密了消息 我将字节作为字符串发送 某些加密字符无法被控制台读取,因此程序无法执行某些关键操作来处理消息

还是谢谢大家:)

【讨论】:

    【解决方案2】:

    您的代码缺少一些重要的信息。例如进口。他们向我们展示了您使用了哪些库,并让我们有机会进行一些研究。

    1) 例如这行:

    myListener = new Timer(250, readLine);
    

    它不能是 java.util.Timer,因为这个类没有构造函数(long/int,ActionListener)。可能这个调用只运行一次而不是多次,但我无法知道并告诉你。

    2) 另一个例子:你有这条线

    acceptClient.start();
    

    我只能假设有一个实例变量

    Accepter acceptClient = new Accepter();
    

    但它也可以引用完全不同的类,其工作方式不同。

    3)回到我的第一个例子:

    您正在进行某种投票。这在 java 中不是很好的风格,因为 Java Thready 在设计上针对阻塞线程进行了优化。改用这样的代码块(未经测试;受您的服务器代码启发)

    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");
            }
        }
    }
    

    在这种情况下,您不需要轮询并且可以立即响应。这消耗更少的CPU。 一个完全不同的选择是使用 Java NIO,它更适合单线程应用程序(或者我们称之为少线程)。

    一些题外话:

    旧约 1) 调用像 JOptionPane.showMessageDialog()setText() 这样的 Swing 函数对于线程来说是危险的。 Swing 本身不是线程安全的。您应该在它周围使用EventQueue.invokeLater() 包装器。我最喜欢的:SwingUtils.invokeLater()

    旧约 2) 拥有变量tempReceiver class-global(我假设这是因为我看不到任何声明)也很危险,因为您可能会在其他地方使用它,并且可能在另一个readLine()exStr() 调用期间完全覆盖它线程(如果 Timer 是 Swing 实现,它会运行一个额外的线程)。

    旧约 3) 您说的是“.jar 客户端和服务器已相互连接”。这是否意味着您有两个打开的控制台窗口,每个窗口中都运行一个java -jar 命令?如果没有,您可能会错过一些重要的控制台输出(可能是例外)。 java的windows发行版有2个java运行器:javaw.exe,当在资源管理器中双击一个.jar文件时调用它。还有java.exe,它也运行你的程序,但也打开一个控制台窗口,显示System.out.println等的输出。这个控制台对于调试非常重要。它显示与 NetBeans 或 Eclipse 中的调试窗口相同的输出。

    【讨论】:

    • 我只是问你如何调用你的程序。您是否在 Windows 资源管理器中双击该 jar?然后你应该打开一个命令行窗口并输入一个以java开头的命令,否则你会错过代码中任何地方出现的所有System.outSystem.errprintStackTrace输出。关于您的readLine 更改:您仍在投票。这个想法是在没有socketIn.ready 的情况下调用readLine()。 readLine 将阻塞线程并等待直到有传入数据。这可以立即响应您的应用程序。 - 请告诉我们 Timer 类的包名
    • 感谢您的投票技巧!不过,我确实对其进行了一些更改以适应我的需要。好吧,我已经更新了我的帖子,它包含更完整的代码。对不起,但我真的不明白控制台窗口的事情。我应该使用命令提示符来运行 java
    • 是的,我在 windows exploler 中双击 jar。我使用javax.swing.Timer 包。我明白了,我想知道我现在应该如何应用你的 readLine 技巧了。好吧,回到主要问题,我的应用程序在 netbeans 中运行良好,但是当我双击 jar 文件时它不起作用
    • 我看到两个可能的问题:竞争条件或缺少库。最后一个向控制台抛出异常。请打开命令行窗口并调用java -jar &lt;yourjarfile&gt;
    • 好的,我现在找到了 javadoc。之前找错班了。轮询似乎没问题,但不是最佳的。也许有一个竞争条件。尝试观看控制台。如有必要,请进行更多调试输出,如下所示:System.err.println("Connection established")
    猜你喜欢
    • 2016-02-28
    • 2017-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多