简体   繁体   English

Java Server类和套接字连接问题

[英]Issue with Java Server class and socket connections

I am trying to set up a server class, and i'm running into a issue in which no error is being thrown. 我正在尝试设置服务器类,并且遇到了没有引发任何错误的问题。

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

public class Server extends JFrame implements Runnable{

private static final long serialVersionUID = 1L;
private JTextField userText;
private JTextArea chatWindow;
private ObjectOutputStream output;
private ObjectInputStream input;
private ServerSocket server;
private Socket connection;

//constructor
public Server(){
    super("Server");
    userText = new JTextField();
    userText.setEditable(false);
    userText.addActionListener(
        new ActionListener(){
            public void actionPerformed(ActionEvent event){
                sendMessage(event.getActionCommand());
                userText.setText("");
            }
        }
    );
    add(userText, BorderLayout.NORTH);
    chatWindow = new JTextArea();
    add(new JScrollPane(chatWindow));
    setSize(300, 150); //Sets the window size
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);   
}

public void run(){
    try{
        server = new ServerSocket(6789, 100); //6789 is a dummy port for testing, this can be changed. The 100 is the maximum people waiting to connect.
        while(true){
            try{
                //Trying to connect and have conversation
                waitForConnection();
                setupStreams();
                whileChatting();
            }catch(EOFException eofException){
                showMessage("\n Server ended the connection! ");
            } finally{
                closeConnection(); //Changed the name to something more appropriate
            }
        }
    } catch (IOException ioException){
        ioException.printStackTrace();
    }
}
//wait for connection, then display connection information
private void waitForConnection() throws IOException{
    showMessage(" Waiting for someone to connect... \n");
    connection = server.accept();
    showMessage(" Now connected to " + connection.getInetAddress().getHostName());
}

//get stream to send and receive data
private void setupStreams() throws IOException{
    output = new ObjectOutputStream(connection.getOutputStream());
    output.flush();

    input = new ObjectInputStream(connection.getInputStream());

    showMessage("\n Streams are now setup \n");
}

//during the chat conversation
private void whileChatting() throws IOException{
    String message = " You are now connected! ";
    sendMessage(message);
    ableToType(true);
    do{
        try{
            message = (String) input.readObject();
            showMessage("\n" + message);
        }catch(ClassNotFoundException classNotFoundException){
            showMessage("The user has sent an unknown object!");
        }
    }while(!message.equals("CLIENT - END"));
}

public void closeConnection(){
    showMessage("\n Closing Connections... \n");
    ableToType(false);
    try{
        output.close(); //Closes the output path to the client
        input.close(); //Closes the input path to the server, from the client.
        connection.close(); //Closes the connection between you can the client
    }catch(IOException ioException){
        ioException.printStackTrace();
    }
}

//Send a mesage to the client
private void sendMessage(String message){
    try{
        output.writeObject("SERVER - " + message);
        output.flush();
        showMessage("\nSERVER -" + message);
    }catch(IOException ioException){
        chatWindow.append("\n ERROR: CANNOT SEND MESSAGE, PLEASE RETRY");
    }
}

//update chatWindow
private void showMessage(final String text){
    SwingUtilities.invokeLater(
        new Runnable(){
            public void run(){
                chatWindow.append(text);
            }
        }
    );
}

private void ableToType(final boolean tof){
    SwingUtilities.invokeLater(
        new Runnable(){
            public void run(){
                userText.setEditable(tof);
            }
        }
    );
 }
 }



import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class Menu extends JFrame implements ActionListener{

private static final long serialVersionUID = 1L;
private JButton server;
private JButton client;
private static String Host;

public Menu(){

    this.getContentPane().setPreferredSize(new Dimension(300, 300));

    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setLayout(null);
    this.pack();

    this.setLocationRelativeTo(null);

    server = new JButton();
    server.setText("server");
    server.setBounds(0, 0, 300, 150);
    server.addActionListener(this);
    client = new JButton();
    client.setText("client");
    client.setBounds(0, 150, 300, 150);
    client.addActionListener(this);

    this.add(server);
    this.add(client);

    this.setVisible(true);
}


public void actionPerformed(ActionEvent e) {
    if(e.getSource() == server){
        Server s = new Server();
        s.run();
    }
    if(e.getSource() == client){
        Host = JOptionPane.showInputDialog("Enter Server I.P.");
        Client c = new Client(Host);
        c.run();
    }

}

public static void main(String[] args){
    new Menu();
}

}

The JFrame is created, but can only be exited by the termination button in eclipse, not the default_exit_on_close operation, and is see through (not opaque as it should be). JFrame已创建,但只能通过eclipse中的终止按钮退出,不能通过default_exit_on_close操作退出,并且可以透视(应该是不透明的)。 The client class acts the same way, leading me to believe that the issue is the: 客户类的行为方式相同,使我相信问题在于:

 Server s = new Server();
        s.run(); 

since if i have the main method call that, everything works fine. 因为如果我有main方法调用,一切正常。

Your constructor can never exit. 您的构造函数永远不会退出。

This waitForConnection()/setUpStreams() logic is not appropriate. waitForConnection()/setUpStreams()逻辑不合适。 You need an accept loop that just accepts sockets, constructs a Runnable to handle the connection, and starts a thread. 您需要一个accept 循环 ,该循环只接受套接字,构造一个Runnable来处理连接,并启动一个线程。 That loop should be in a separate run() method and be executed in a separate thread. 该循环应在单独的run()方法中,并在单独的线程中执行。 Not in a constructor. 不在构造函数中。

NB The Socket that is returned by accept() must be a local variable in that loop, otherwise you are liable to run into concurrency problems. 注意由accept()返回的Socket必须是该循环中的局部变量,否则您可能会遇到并发问题。

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

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