简体   繁体   English

Java - Threads,Swing和ServerSocket

[英]Java - Threads, Swing, and ServerSocket

I know I know, already a million questions and answers on this everywhere. 我知道我知道,到处都有一百万个问题和答案。 Tons of really detailed articles on it, several types of examples. 关于它的大量详细文章,几种类型的例子。 I've spent the past few hours reading about it, but that's not doing the trick. 过去几个小时我一直在阅读它,但这并没有成功。 The reason I'm asking this is because I still don't quiet understand what I need to do apparently because my code is still not working. 我问这个的原因是因为我仍然不明白我需要做什么显然是因为我的代码仍然无效。 I get the idea of how Swing works with the EDT, and if I'm going to use the ServerSocket's accept() method I'm going to need to start a new thread for Swing (I think?). 我知道Swing如何与EDT一起工作,如果我要使用ServerSocket的accept()方法,我将需要为Swing启动一个新线程(我想?)。 When I run my code as it is the window just opens and freezes. 当我运行我的代码时,窗口就会打开并冻结。 My question is could someone look at my code, tell me what I'm doing wrong, and explain it to me like I only have half a brain? 我的问题是,有人可以看看我的代码,告诉我我做错了什么,并向我解释,因为我只有半个大脑? (Because that's what I feels like. :P ) (因为那就是我的感受。:P)

Here are some of the places I've read already: 以下是我已经读过的一些地方:

Main.class 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 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 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 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"){

    }
}

}

--EDIT--- The new Main.class with SwingWorker --EDIT ---带有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) {

    }
}
}

You are reading from your Socket on the EDT. 您正在阅读EDT上的Socket。 This means that you block it. 这意味着你阻止了它。 Calling invokeLater only causes your Runnable to be executed on the EDT. 调用invokeLater只会导致您的Runnable在EDT上执行。 You are piling two calls on the EDT, one of them being your socket. 你在EDT打了两个电话,其中一个是你的插座。

Consider moving your socket in a SwingWorker which returns progressively the values of your Socker to the GUI. 考虑在SwingWorker中移动套接字,该套接字将Socker的值逐步返回到GUI。

Socket operations block. 套接字操作阻止。 For instance, if you call accept , the call will not return until someone actually connects to your program, effectively blocking the thread it's running on. 例如,如果您调用accept ,则在实际连接到您的程序之前,调用将不会返回,从而有效地阻止正在运行的线程。 That's why they suggest to have the networking run on a secondary thread. 这就是为什么他们建议让网络在辅助线程上运行。

In your case, you do create a thread, but you don't call accept from it. 在您的情况下,您确实创建了一个线程,但是您没有从中调用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.");
    }
}

This is why it freezes. 这就是冻结的原因。 The call to accept must be done from the secondary thread if you don't want to block the UI. 如果您不想阻止UI,则必须从辅助线程完成对accept的调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM