2

私は知っています、これについてはすでに百万の質問と回答がどこにでもあります。それに関するたくさんの本当に詳細な記事、いくつかのタイプの例。私は過去数時間それについて読んでいました、しかしそれはトリックをしていません。私がこれを求めている理由は、コードがまだ機能していないために、どうやら何をする必要があるのか​​まだ静かに理解していないからです。SwingがEDTでどのように機能するかがわかり、ServerSocketのaccept()メソッドを使用する場合は、Swingの新しいスレッドを開始する必要があります(私は思いますか?)。コードをそのまま実行すると、ウィンドウが開いてフリーズします。私の質問は、誰かが私のコードを見て、私が間違っていることを教えて、私が半分の脳しか持っていないようにそれを私に説明できるかどうかです。(それが私が感じているものだからです。:P)

これが私がすでに読んだ場所のいくつかです:

Main.class

package com.sever.core;

import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;

import javax.swing.SwingUtilities;

public class Main { 

private SocketManager network;
public static void main(String[] args){

    SwingUtilities.invokeLater(new Runnable(){
        @Override
        public void run() {
            Window window = new Window();
            window.setVisible(true);
        }       
    });

    SwingUtilities.invokeLater(new Runnable(){
        @Override
        public void run() {
            Main main = new Main();
            main.run();
        }       
    });     


}

public void run(){
    network = new SocketManager(25595);

    while(true){
        try {
            network.setSocket(network.getServerSocket().accept());
            AddUser(network.getSocket());
            Thread x = new Thread(network);
            x.start();
        } catch (Exception e) {
            System.out.println("Failed to connect.");
        }
    }

}

public void AddUser(Socket s){
    try {
        Scanner input = new Scanner(s.getInputStream());
        network.addUser(input.nextLine());
    } catch (Exception e) {

    }
}
}

Window.class

package com.sever.core;

import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.*;

public class Window extends JFrame{

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

private JPanel window = new JPanel();
private JTextArea consle = new JTextArea("Server started....");
private JTextField input = new JTextField();
private JScrollPane consleinput = new JScrollPane(consle);

public Window(){
    this.setName("NAMEHERE - Server Software");
    setResizable(true);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(screenWidth,screenHeight);  
    window.setBackground(Color.DARK_GRAY);
    window.setLayout(new BoxLayout(window, BoxLayout.Y_AXIS));

    consleSetup();
    addComponets();
}

private void addComponets(){
    add(window);
    window.add(consleinput);
    window.add(input);
}

private void consleSetup(){
    consle.setEditable(false);
    consle.setLineWrap(true);
    consle.setBorder(BorderFactory.createEmptyBorder(3,3,3,3)); 
    consleinput.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    input.setMaximumSize(new             Dimension(Integer.MAX_VALUE,input.getPreferredSize().height));
}

private void addListeners(){
    input.addActionListener(new ActLis());
    input.setActionCommand("input");
}

}

SocketManager.class

package com.sever.core;

import java.io.*;
import java.net.*;
import java.util.ArrayList;

public class SocketManager implements Runnable{

private Socket sock;
private ServerSocket sersoc;
private PrintWriter output;
private BufferedReader input;
private Thread thread;

public ArrayList<Socket> currentConnections = new ArrayList<Socket>();
public ArrayList<String> currentUsers = new ArrayList<String>();


public SocketManager(String ip, int port){
    try{
        sock = new Socket(ip,port);
        PrintWriter output = new PrintWriter(sock.getOutputStream());
        BufferedReader input = new BufferedReader(
                new InputStreamReader(sock.getInputStream()));
        System.out.println("Server: socket started.");
    }catch(Exception e){
        System.out.println("Server: Socket failed to connect.\n");
    }
}

public SocketManager(int port){
    try {
        sersoc = new ServerSocket(port);

    } catch (IOException e) {
        System.out.println("Server: Socket failed to connect.\n");
    }
}

public SocketManager(Socket socket){
    this.sock = socket;

    try{
        output = new PrintWriter(sock.getOutputStream());
        input = new BufferedReader(
                new InputStreamReader(sock.getInputStream()));
    }catch(Exception e){

    }
}

public synchronized void checkConnetion(){
    if(!sock.isConnected()){
        for(int x = 0; x <= currentConnections.size(); x++){
            if(currentConnections.get(x) == sock){
                currentConnections.remove(x);
                System.out.println("Server: Disconnecting from: " + currentConnections.get(x) + "\n");
            }
        }
    }
}

public synchronized Socket getSocket(){
    return sock;
}

public synchronized ServerSocket getServerSocket(){
    return sersoc;
}

public synchronized void setSocket(Socket s){
    System.out.println("Setting socket to: " + s.getInetAddress());
    sock = s;
}

public synchronized void addSocket(Socket s){
    currentConnections.add(s);
}

public synchronized void addUser(String u){
    currentUsers.add(u);
}

public synchronized ArrayList<Socket> getConnections(){
    return currentConnections;
}

public synchronized ArrayList<String> getUsers(){
    return currentUsers;
}

public synchronized void send(String data){
    try{
        output.println(data);
    }catch(Exception e){

    }
}

public synchronized void close(){
    try{
        sock.close();
    }catch(Exception e){

    }
    output = null;
    input = null;
    System.gc();
}

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

@Override
public void run() {
    System.out.println("Is runing.");
    while(true){
        try {
            checkConnetion();
            if(input.readLine().isEmpty()){ 
                return;
            }

            output.println("Server: Recived your message.");
        } catch (Exception e) {

        } finally{
            try {
                sock.close();
            } catch (Exception e) {

            }
        }
    }

}

}

ActLis.class

package com.sever.core;

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

public class ActLis implements ActionListener{

private JTextField actionField;
public ActLis(){

}

public ActLis(JTextField t){
    actionField = t;
}

@Override
public void actionPerformed(ActionEvent e) {
    // TODO Auto-generated method stub
    String cmd = e.getActionCommand();

    if(cmd == "input"){

    }
}

}

--編集--- SwingWorkerを使用した新しいMain.class

package com.sever.core;

import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;

import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class Main { 

private SocketManager network;
public static void main(String[] args){

    SwingUtilities.invokeLater(new Runnable(){
        @Override
        public void run() {
            Window window = new Window();
            window.setVisible(true);
        }       
    });

    SwingWorker server = new SwingWorker(){
        @Override
        protected Object doInBackground() throws Exception {
            Main main = new Main();
            main.run();
            return null;
        }

    };
    server.run();

}

public void run(){
    network = new SocketManager(25595);

    while(true){
        try {
            network.setSocket(network.getServerSocket().accept());
            AddUser(network.getSocket());
            Thread x = new Thread(network);
            x.start();
        } catch (Exception e) {
            System.out.println("Failed to connect.");
        }
    }

}

public void AddUser(Socket s){
    try {
        Scanner input = new Scanner(s.getInputStream());
        network.addUser(input.nextLine());
    } catch (Exception e) {

    }
}
}
4

2 に答える 2

7

EDTのソケットから読み取っています。これはあなたがそれをブロックすることを意味します。invokeLaterを呼び出すと、RunnableはEDTでのみ実行されます。EDTに2つの呼び出しを積み上げており、そのうちの1つがソケットです。

Sockerの値をGUIに段階的に返すSwingWorkerでソケットを移動することを検討してください。

于 2012-05-13T22:52:18.327 に答える
2

ソケット操作ブロック。たとえば、を呼び出すとaccept、誰かが実際にプログラムに接続するまで呼び出しは返されず、実行中のスレッドが効果的にブロックされます。そのため、ネットワークをセカンダリスレッドで実行することを提案しています。

あなたの場合、あなたはスレッドを作成しますが、acceptそれから呼び出すことはありません。

while(true) {
    try {
        // this is called on the EDT--beware!
        network.setSocket(network.getServerSocket().accept());
        AddUser(network.getSocket());
        // ... and then, everything called from x will be on the secondary thread
        Thread x = new Thread(network);
        x.start();
    } catch (Exception e) {
        System.out.println("Failed to connect.");
    }
}

これがフリーズする理由です。acceptUIをブロックしたくない場合は、の呼び出しをセカンダリスレッドから実行する必要があります。

于 2012-05-13T22:48:06.950 に答える