3

チャットプログラムに取り組んでいるので、ファイル送信オプションを追加したいと思います。追加してみましたが、ファイル転送が終了した直後に、両方のソケット(2つのクライアントのソケット)が閉じます。チャットクライアントのSSCCEは次のとおりです。

public class SSCCEChatClient extends JFrame {

    private JPanel contentPane;
    private JTextField inputUsernameField;
    private JTextArea textArea;
    String serversock = "84.252.37.82";
    String username;
    Socket sock;
    BufferedReader reader;
    PrintWriter writer;
    InputStreamReader streamreader;

    public class IncomingReader implements Runnable{

        public void run() {
            String stream;
            String[] data;

            try {
                while ((stream = reader.readLine()) != null) {

                    data = stream.split("`");
                     if(data[2].equals("receiveFile")&&(!data[3].equals(username))){
                        DataInputStream in = new DataInputStream(sock.getInputStream());
                        byte[] bytes = new byte[Integer.parseInt(data[1])];
                        in.read(bytes);
                        FileOutputStream fos = new FileOutputStream(System.getProperty("user.home") + "\\Desktop\\" + data[0]);
                        fos.write(bytes);
                        fos.close();
                        in.close();
                        textArea.append("Success!");
                    }else if(data[2].equals("server")){
                        textArea.append(data[0]);
                    }

                }
           }catch(Exception ex) {
           }
        }
    }//Incoming Reader

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    SSCCEChatClient frame = new SSCCEChatClient();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public SSCCEChatClient() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);

        textArea = new JTextArea();
        contentPane.add(textArea, BorderLayout.SOUTH);

        JButton btnNewButton = new JButton("Send File");
        btnNewButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                File transferFile = new File (System.getProperty("user.home") + "\\Desktop\\PNG\\Night.png");
                byte [] bytearray  = new byte [(int)transferFile.length()];
                try {
                    BufferedInputStream bin = new BufferedInputStream(new FileInputStream(transferFile));
                    bin.read(bytearray,0,bytearray.length);
                    DataOutputStream os = new DataOutputStream(sock.getOutputStream());
                    writer.println(transferFile.getName() + "`" + transferFile.length() + "`receiveFile`" + username);
                    writer.flush();
                    os.write(bytearray,0,bytearray.length);
                    os.flush();
                    bin.close();
                    os.close();

                } catch (IOException e) {
                    e.printStackTrace();
                }
                System.out.println("File transfer complete");
            }
        });
        contentPane.add(btnNewButton, BorderLayout.CENTER);

        JButton btnNewButton_1 = new JButton("Connect");
        btnNewButton_1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    username = inputUsernameField.getText();
                    sock = new Socket(serversock, 5000);
                    streamreader = new InputStreamReader(sock.getInputStream());
                    reader = new BufferedReader(streamreader);
                    writer = new PrintWriter(sock.getOutputStream());
                    Thread IncomingReader = new Thread(new IncomingReader());
                    IncomingReader.start();
                    writer.println(username + "``connect");
                    writer.flush();

                } catch (Exception ex) {
                    textArea.append("\nCannot Connect!");
                }
            }
        });
        contentPane.add(btnNewButton_1, BorderLayout.WEST);

        inputUsernameField = new JTextField();
        contentPane.add(inputUsernameField, BorderLayout.NORTH);
        inputUsernameField.setColumns(10);
    }

}

これがサーバー側です。

public class SSCCEServer {
    static ArrayList<PrintWriter> clientOutputStreams;
    static ArrayList<DataOutputStream> clientDataOutputStreams;
    static ArrayList<String> onlineUsers = new ArrayList<>();
    public class ClientHandler implements Runnable  {
        BufferedReader reader;
        Socket sock;
        PrintWriter client;


        public ClientHandler(Socket clientSocket, PrintWriter user) {
        // new inputStreamReader and then add it to a BufferedReader
            client = user;
            try {
                sock = clientSocket;
                System.out.println(clientSocket.getRemoteSocketAddress().toString() + " - ");
                InputStreamReader isReader = new InputStreamReader(sock.getInputStream());
                reader = new BufferedReader(isReader);
            }
            catch (Exception ex) {
                System.out.println("error beginning StreamReader");
            }

        }

        public void run() {
            String message;
            String[] data;
            try {
                while ((message = reader.readLine()) != null) {

                    data = message.split("`");

                    if(data[2].equals("receiveFile")){
                        DataInputStream in = new DataInputStream(sock.getInputStream());
                        byte[] bytes = new byte[Integer.parseInt(data[1])];
                        in.read(bytes);
                        tellEveryone(data[0] + "`" + data[1] + "`" + data[2] + "`" + data[3]);
                        for(DataOutputStream dos:clientDataOutputStreams){
                            try {
                                dos.write(bytes);
                                dos.close();
                            }
                            catch (Exception ex) {
                                System.out.println("error telling everyone");
                            }
                        }
                        tellEveryone("File transfer complete``server");
                    }else if(data[2].equals("connect")){
                        System.out.println(data[0] + "has connected.");
                    }else {
                        System.out.println("No Conditions were met.");
                      }
                 }
            }
            catch (Exception ex) {
                System.out.println("lost a connection");
                System.out.println(ex.getMessage().toString());
                clientOutputStreams.remove(client);
            }
        }
    }
    public void tellEveryone(String message) {
    // sends message to everyone connected to server
        for(PrintWriter writer:clientOutputStreams){
                try {
                    writer.println(message);
                    //pop("Sending: " + message);
                    writer.flush();
                }
                catch (Exception ex) {
                    System.out.println("error telling everyone");
                }
        }
       }
    public static void main(String[] args) {
        new SSCCEServer().go();
    }
    public void go(){
        clientOutputStreams = new ArrayList<PrintWriter>();
        clientDataOutputStreams = new ArrayList<>();

        try {
            @SuppressWarnings("resource")
            ServerSocket serverSock = new ServerSocket(5000);
            while(true){
                Socket clientSock = serverSock.accept();
                PrintWriter writer = new PrintWriter(clientSock.getOutputStream());
                clientOutputStreams.add(writer);
                clientDataOutputStreams.add(new DataOutputStream(clientSock.getOutputStream()));
                Thread listener = new Thread(new ClientHandler(clientSock, writer));
                listener.start();
            }
        } 
        catch (Exception ex)
        {
            System.out.println("error making a connection");
        }
    }

}

本当に長い場合は申し訳ありませんが、これは私が持っていくことができる最小限の量です。また、テキスト送信メソッドがないため、すべてではありませんが、SSCCEには影響しません。サーバー側からメソッド「tellEveryone」を使用してsendメソッドをデモンストレーションしました。また、「\ PNG \ Night.png」は単なる例であり、SSCCEを実行するために独自のフォルダとファイルを作成できます。ファイルが送信された後、ソケットのクローズを修正するにはどうすればよいですか?

4

2 に答える 2

3
  1. ブロック内のすべてObjectsを閉じる( )finallytry - catch - finally

  2. Swingの同時実行性に問題がありますが、3つの方法があります

    a)適切な方法

    • コードをRunnable#Thread(最も簡単な)にラップし、SwingGUIへの変更をにラップする必要がありますinvokeLater()

    • 使用SwingWorker(標準的な方法で実装)、メソッドpublishprocessおよびすべてが実行doneされることをかなり保証しますeventsEDT

    b)ショートカット、機能するが適切な方法ではない

    • SwingGUIコードをinvokeLater()直接ラップする
于 2012-12-31T15:48:20.027 に答える
1

出力ストリームを閉じると、ソケットが閉じます。ソケットを開いたままにしておきたい場合は、ストリームを閉じないでください。参考までにご覧くださいSocketOutputStream.java

于 2012-12-31T15:46:50.713 に答える