【问题标题】:Add a thread to handle only 1 socket per time添加一个线程以每次仅处理 1 个套接字
【发布时间】:2013-10-04 18:19:38
【问题描述】:

我如何在该代码中添加一个线程以允许每次仅 1 个连接...以及何时完成 .close();再次打开等待另一个?我尝试了很多其他的东西,比如 WHILE、if 和其他变量,但未能阻止 .accept();当连接打开时;/,我不知道如何使它成为一个线程

import java.awt.Desktop;
import java.io.*;
import java.lang.reflect.Array;
import java.net.*;
import java.util.ArrayList;

import javax.swing.JOptionPane;
import javax.swing.JTextField;
public class Provider  {
    ServerSocket providerSocket;
    Socket connection = null;
    ObjectOutputStream out;
    String ocupado = "0";
    ObjectInputStream in;
    String caminhodoarquivo;
    Provider(){}
    void run()
    {
        try{
            providerSocket = new ServerSocket(2004, 1);
            System.out.println("---------------Aguardando por certidões----------------");          
            connection = providerSocket.accept();  
            out = new ObjectOutputStream(this.connection.getOutputStream());
            out.flush();
            sendMessage(ocupado);
            in = new ObjectInputStream(connection.getInputStream());

            System.out.println("Certidão de: " + connection.getInetAddress().getHostName());
            String ocupado = "1";


                try{
                    caminhodoarquivo = (String)in.readObject();
                   System.out.println("Certidão: " + caminhodoarquivo);

                   JTextField paginainicial = new JTextField();
                   JTextField paginafinal = new JTextField();
                   Object[] message = {
                        "Número da Primeira Folha: ", paginainicial,
                        "Número Última Folha: ", paginafinal,
                    };

                int option = JOptionPane.showConfirmDialog(null, message, "Dados da Certidão", JOptionPane.OK_CANCEL_OPTION);
                ocupado = "1";
                if (option == JOptionPane.OK_OPTION) {

                    String primeirafolha = paginainicial.getText();
                    String ultimafolha = paginafinal.getText();
                    metodos metodosBD = new metodos();
                    metodosBD.atualizafolha(primeirafolha, ultimafolha, caminhodoarquivo);

                    System.out.println("Dados inseridos.");
                    Desktop.getDesktop().print(new File(caminhodoarquivo)); 
                    ocupado = "0";


                } else {
                    System.out.println("Certidão Cancelada.");

                }


                }
                catch(ClassNotFoundException classnot){
                    System.err.println("Data received in unknown format");
                    out.close();
                    in.close();
                    providerSocket.close();
                }



        }
        catch(IOException ioException){
            ioException.printStackTrace();
        }
        finally{
            //4: Closing connection
            try{
                in.close();
                out.close();
                providerSocket.close();
            }
            catch(IOException ioException){
                ioException.printStackTrace();
            }
        }
    }

    void sendMessage(String msg)
    {
        try{
            out.writeObject(msg);
            out.flush();
        }
        catch(IOException ioException){
            ioException.printStackTrace();
        }
    }
    public static void main(String args[])
    {
        Provider server = new Provider();
        while(true){
            server.run();
        }
    }

}

编辑 user2511414 的答案

1) 服务器运行正常并完美接收第一个连接并在我关闭确认对话框时完成它,我可以完美打开另一个 = OK

2) 当我连接客户端 1 时,保持确认对话框打开,然后尝试连接第二个客户端,我在客户端 2 中收到此错误:

java.net.SocketException: Software caused connection abort: recv failed
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.read(Unknown Source)
        at java.net.SocketInputStream.read(Unknown Source)
        at java.io.ObjectInputStream$PeekInputStream.read(Unknown Source)
        at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)
        at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Sour
ce)
        at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
        at java.io.ObjectInputStream.<init>(Unknown Source)
        at certidoesOrganizado.PrimeiroPDF$Requester.run(PrimeiroPDF.java:151)
        at certidoesOrganizado.PrimeiroPDF.enviacaminho(PrimeiroPDF.java:132)
        at certidoesOrganizado.PrimeiroPDF.geracertidao(PrimeiroPDF.java:466)
        at certidoesOrganizado.PrimeiroPDF.pegadados(PrimeiroPDF.java:302)
        at certidoesOrganizado.gui$6.actionPerformed(gui.java:204)

在服务器中我收到了这个:

java.net.SocketException: Socket is closed
        at java.net.Socket.getOutputStream(Unknown Source)
        at Provider.run(Provider.java:21)
        at java.lang.Thread.run(Unknown Source)
Exception in thread "Thread-4" java.lang.NullPointerException
        at Provider.run(Provider.java:59)
        at java.lang.Thread.run(Unknown Source)

并且 Client2 没有收到“服务器正忙消息”

3) 当 client1 ConfirmDialog 仍然打开并且在 Client2 失败后我尝试 CLIENT3,它成功连接并且我以 2 Joption.ShowConfirmDialog 打开结束... :(

一切重新开始,我在 CLIENT 中使用它来进行连接:

在调用连接的方法中:

Requester client = new Requester();

client.run();

课程请求者:

}
class Requester{
    Socket requestSock

et;
        ObjectOutputStream out;
    ObjectInputStream in;
    String message;

    Requester(){}
    void run()



    {




        try{

                requestSocket = new Socket("localhost", 2004);



            System.out.println("Tentando Conexão");
            out = new ObjectOutputStream(requestSocket.getOutputStream());
            out.flush();            
            System.out.println("out.flush");
            in = new ObjectInputStream(requestSocket.getInputStream());

                try {
                    message = (String)in.readObject();
                } catch (ClassNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }







            do{
               message = "oi";
                sendMessage(arquivonomecompleto);
            }while(message.equals("bye"));

        }
        catch(UnknownHostException unknownHost){
            System.err.println("You are trying to connect to an unknown host!");
        }
        catch(IOException ioException){
            ioException.printStackTrace();
        }
        finally{
            //4: Closing connection
            try{
                in.close();
                out.close();
                requestSocket.close();
            }
            catch(IOException ioException){
                ioException.printStackTrace();
            }
        }


    }

    void sendMessage(String msg)
    {
        try{
            out.writeObject(msg);
            out.flush();
            //System.out.println("client>" + msg);
        }
        catch(IOException ioException){
            ioException.printStackTrace();
        }
    }




}

【问题讨论】:

    标签: java multithreading sockets


    【解决方案1】:

    我看到你的代码单线程,没有其他线程的迹象,一切都由主线程运行,其次我对某些部分有点困惑,首先你在得到它之后刷新输出,我的意思是你不发送任何东西但冲洗它!

    out = new ObjectOutputStream(this.connection.getOutputStream());
    out.flush();
    

    那么您如何看待您的应用程序并行运行?!

    关于在另一个线程(和单线程)中运行连接过程,这不是一件很难的工作,首先实现Runnable接口,让run方法处理连接处理。

    public class Provider implements Runnable  {
      ...
      public void run(){//manages the connection but ONE at a time.
        while(true){
           server.run();
        }
      }
      public static void main(String[] arg){
        Provider server = new Provider();
        new Thread(this).start();//start the connection processing with another thread.
      }
      ...
    }
    

    你也会有一个简单的thread tutorial here。 有一个很好的并行程序老兄:)

    更新: 并在第一个进程正在进行时拒绝第二个(带有一些消息),所以这也不是一项艰巨的工作,但第一件事是使进程并行,为此,我把main方法放到了另一个类中,让Provider类处理请求,同时保持ServerSocket(port) OEPN。

    import java.awt.Desktop;
    import java.io.*;
    import java.lang.reflect.Array;
    import java.net.*;
    import java.util.ArrayList;
    
    import javax.swing.JOptionPane;
    import javax.swing.JTextField;
    public class Provider implements Runnable {
       // ServerSocket providerSocket;
        Socket connection = null;
        ObjectOutputStream out;
        String ocupado = "0";
        ObjectInputStream in;
        String caminhodoarquivo;
        Provider(Socket s){this.connection=s;}
        @Override
        public void run()
        {
            try{
                out = new ObjectOutputStream(this.connection.getOutputStream());
                //out.flush();
                sendMessage(ocupado);
                in = new ObjectInputStream(connection.getInputStream());
                System.out.println("Certidão de: " + connection.getInetAddress().getHostName());
                String ocupado = "1";
                    try{
                        caminhodoarquivo = (String)in.readObject();
                       System.out.println("Certidão: " + caminhodoarquivo);
                       JTextField paginainicial = new JTextField();
                       JTextField paginafinal = new JTextField();
                       Object[] message = {
                            "Número da Primeira Folha: ", paginainicial,
                            "Número Última Folha: ", paginafinal,
                        };
                    int option = JOptionPane.showConfirmDialog(null, message, "Dados da Certidão", JOptionPane.OK_CANCEL_OPTION);
                    ocupado = "1";
                    if (option == JOptionPane.OK_OPTION) {
                        String primeirafolha = paginainicial.getText();
                        String ultimafolha = paginafinal.getText();
                        metodos metodosBD = new metodos();
                        metodosBD.atualizafolha(primeirafolha, ultimafolha, caminhodoarquivo);
                        System.out.println("Dados inseridos.");
                        Desktop.getDesktop().print(new File(caminhodoarquivo)); 
                        ocupado = "0";
                    }else {System.out.println("Certidão Cancelada.");}
                    }catch(ClassNotFoundException classnot){
                        System.err.println("Data received in unknown format");
                        out.close();
                        in.close();
                        connection.close();
                    }
            }
            catch(IOException ioException){ioException.printStackTrace();}
            finally{
                Server.setFree();//Tells server the system is ready for new connection.
                //4: Closing connection
                try{
                    in.close();
                    out.close();
                    connection.close();
                }
                catch(IOException ioException){
                    ioException.printStackTrace();
                }
            }
        }
    
        void sendMessage(String msg)
        {
            try{
                out.writeObject(msg);
                out.flush();
            }
            catch(IOException ioException){
                ioException.printStackTrace();
            }
        }
    //    public static void main(String args[])
    //    {
    //        Provider server = new Provider();
    //        while(true){
    //            server.run();
    //        }
    //    }
    
    }
    

    注意:当服务器忙时,这个响应“错误->服务器忙”作为字符串,因此客户端需要检查服务器响应单个字符串“错误->服务器忙”这意味着服务器没有响应任何内容否则。

    class Server implements Runnable{
      private final String serverBusyMessage="Error -> Server is busy";
      private ServerSocket ss;
      private static volatile boolean busy=false;
      public static void setFree(){busy=false;}
      public void run(){
        while(true){
           try{Socket s=ss.accept();
               if(busy){//if there is one connection processing.
                  ObjectOutputStream out=new ObjectOutputStream(s.getOutputStream());
                  out.writeObject(serverBusyMessage);
                  out.flush();
                  s.close();continue;
               }
               System.out.println("---------------Aguardando por certidões----------------");   
               new Thread(new Provider(s)).start();
               busy=true;
           }catch(Exception e){}
        }
      }
      private Server(){try{ss=new ServerSocket(2004);}catch(Exception ex){}}
      public static void main(String[] arg){
        Server server = new Server();
        new Thread(server).start();
      }
    }
    

    【讨论】:

    • out.flush 是我最后使用的是 SendMessage,但我删除了它,我忘记删除了;x 抱歉!!非常感谢这一课:)
    • 好的,好的,我知道了,你知道applciation工作正常,因为客户端会连接,但是没有响应,所以现在你想用一些消息拒绝第二个对吗?!好的,我会更新我的答案。
    • 我很高兴(如果)我可以帮忙,我再次更新答案(在最后一个命令后 1 分钟,所以请刷新页面,因为你可能得到旧的):)
    • @user2582318 我更新了,我忘记了一个关键字,请重新检查,希望这次有效。
    • @user2582318 我真的很高兴我能帮上忙,有一个好的套接字应用程序伙伴:)
    猜你喜欢
    • 2017-06-15
    • 1970-01-01
    • 2012-01-25
    • 1970-01-01
    • 2011-07-05
    • 1970-01-01
    • 1970-01-01
    • 2012-05-17
    • 1970-01-01
    相关资源
    最近更新 更多