socket.Close()暂停程序(java)(请删除)

时间:2017-04-13 23:18:45

标签: java multithreading swing sockets tcp

编辑!:我发现了错误,它在while循环中我们不应该修改......它正在检查连接是否以错误的方式关闭。 所以请,如果任何mod读取此(我标记)...删除。感谢和抱歉造成的任何麻烦。

我正在与Java进行TCP聊天,当我尝试关闭套接字时,作为jFrame窗口的客户端停止工作(加上CPU使用率上升)。 我正在使用带有jdk1.8.0_91的NetBeans 8.1。

我需要关闭连接并初始化它。 我做了一些研究,但仍然找不到任何东西......我错过了什么吗?

提前致谢。

编辑:减少了ChatThread代码,还删除了另一个.java中的coments和一些行...,我认为它仍然太长。道歉。

代码: Project Server,Server.java包含:

 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
 import java.net.Socket;

 public class Server {

 private static final String version = "v0.4(Curry) 07/04/17";
 private static ServerSocket srvSocket;

 public static void main(String[] args) throws IOException {
    int port = -1;
    int maxConnections = 50;

    Socket[] connections = new Socket[maxConnections];
    String[] users = new String[maxConnections];

    System.out.println("Chat Server - " + version + " por Marçal");

    switch (args.length) {
        case 0:
            port = 5667;
            break;
        case 1:
            try {
                port = Integer.parseInt(args[0]);
            } catch (NumberFormatException e) {
                System.out.println("Uso: java -jar chatserver.jar [puerto]");
                System.exit(-1);
            }
            break;
    }

    InetSocketAddress socketAddr = null;
    socketAddr = new InetSocketAddress(port);

    srvSocket = null;
    try {
        srvSocket = new ServerSocket();
        srvSocket.bind(socketAddr);
    } catch (IOException e) {
        System.out.println("Error: imposible conectar");
        System.exit(-1);
    }

    System.out.println("en línea, aceptando conexiones en el puerto " + port + " ...\n");

    int idSocket = 0;
    while (srvSocket != null) {
        try {
            if (connections[idSocket] == null) {

                Socket socket = srvSocket.accept();
                connections[idSocket] = socket;

                if (idSocket % 2 == 0) {
                    users[idSocket] = "John Doe " + idSocket;
                } else {
                    users[idSocket] = "Jane Doe " + idSocket;
                }
                System.out.println("Nueva conexión: id"+idSocket+" ["+connections[idSocket].getInetAddress()+":"+connections[idSocket].getPort()+"]");
                Thread t = new ChatThread(idSocket, maxConnections, connections, users[idSocket]);
                t.start();                    
            }
            idSocket = (idSocket + 1) % maxConnections;
        } catch (IOException e) {
            System.out.println("Error: fallo E/S servidor");
            System.exit(-1);
        }
    }
    srvSocket.close();}}

Project Server,ChatThread.java包含:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class ChatThread extends Thread {

   private final int id;
   private final int maxConnections;
   private final Socket[] conns;
   private final String[] users;
   OutputStream salida;
   InputStream entrada;

public ChatThread(int idSocket, int maxConnections, Socket[] connections, String user) {
    this.maxConnections = maxConnections;
    this.id = idSocket;
    this.conns = connections;
    this.users = new String[this.maxConnections];
    this.users[this.id] = user;    
}

public void run() {
    try {
        String buff;           
        salida = conns[id].getOutputStream();
        entrada = conns[id].getInputStream();  

        salida.write("BLABLA".getBytes());

        conns[id].shutdownInput(); //No Halt
        conns[id].shutdownOutput(); //Halt
        salida.flush();  //Halt          
        salida.close(); //Halt
        entrada.close(); //Halt         
        conns[id].close(); //Halt
         } catch (IOException e) {
         }}}

Project Client,Client.java包含:     包com.chat;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.text.DefaultCaret;

public class Client extends JFrame {

private static final long serialVersionUID = 1L;

private static final String version = "v0.4(Curry) 07/04/17";

private JFrame frmChat;
private JTextField input;
private JTextArea salida;
private JScrollPane scrollPane;

private static InetSocketAddress socketAddr;
private static InputStream is;
private static OutputStream os;

static String text;

public static void main(String[] args) {
    Client window = new Client(args);
    window.frmChat.setVisible(true);

    try {
        Socket cliSocket = new Socket();
        cliSocket.connect(socketAddr);
        window.frmChat.setTitle("Chat " + version + " - " + cliSocket.getLocalAddress().toString() + " [" + cliSocket.getLocalAddress().getCanonicalHostName() + "]");

        is = cliSocket.getInputStream();
        os = cliSocket.getOutputStream();

        window.input.requestFocusInWindow();
        byte[] msg = new byte[100];
        String str;
        text = "";
        do {
            is.read(msg);
            str = new String(msg);
            window.salida.append(str);
            msg = new byte[100];
        } while (!text.equals("SALIR"));

        cliSocket.close();
        window.frmChat.dispose();
    } catch (IOException e) {
        window.salida.setText(e.getMessage());
    }
}

public Client(String[] args) {
    int port = -1;
    switch (args.length) {
        case 0:
            System.out.println("Uso: java -jar chatclient.jar ip|host [puerto]");
            System.exit(0);
            break;
        case 1:
            port = 5667;
            break;
        case 2:
            try {
                port = Integer.parseInt(args[1]);
            } catch (NumberFormatException e) {
                System.out.println("Error: debe especificarse un puerto");
                System.exit(-1);
            }
            break;
    }

    socketAddr = null;
    try {
        socketAddr = new InetSocketAddress(InetAddress.getByName(args[0]), port);
    } catch (UnknownHostException e) {
        System.out.println("Error: host no encontrado / sintaxis incorrecta");
        System.exit(-1);
    }

    initialize();
}

private void initialize() {
    frmChat = new JFrame();
    frmChat.setTitle("Chat");
    frmChat.setResizable(false);
    frmChat.setBounds(100, 100, 441, 411);
    frmChat.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frmChat.getContentPane().setLayout(null);

    salida = new JTextArea();
    salida.setEditable(false);
    salida.setBounds(10, 11, 414, 335);

    DefaultCaret caret = (DefaultCaret) salida.getCaret();
    caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);

    scrollPane = new JScrollPane(salida, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
    scrollPane.setBounds(10, 11, 414, 335);
    frmChat.getContentPane().add(scrollPane);

    input = new JTextField();
    input.setBounds(10, 354, 414, 20);
    frmChat.getContentPane().add(input);
    input.setColumns(100);

    input.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            text = input.getText().trim();
            try {
                if (!text.equals("") && text != null) {
                    os.write(text.getBytes());
                    os.flush();
                }
            } catch (IOException e) {
                salida.append("Error: no se puede enviar");
            }
            input.setText(null);
        }});}}

1 个答案:

答案 0 :(得分:4)

你的问题在这里显现......

do {
    is.read(msg);
    str = new String(msg);
    window.salida.append(str);
    msg = new byte[100];
} while (!text.equals("SALIR"));

您没有注意is.read返回的内容。在服务器端关闭套接字后,这将返回-1,这意味着它已到达文件的末尾"或者没有更多内容可供阅读。

因为你基本上忽略了它,所以do-while循环可以尽可能快地运行,基本上消耗CPU周期并使客户端无用。

注意从套接字读取的字节数很重要,因为它表示两件事,1-当没有什么可读的时候,2-你的阵列中有多少内容可用。这意味着您可以在每次迭代时重用该数组,例如......

int read = -1;
while ((read = is.read(msg)) != -1) {
    str = new String(msg, 0, read);
    if (str.equals("SALIR")) {
        break;
    }
    window.salida.append(str);
}

现在,只要将此代码添加到代码中,框架就会闪烁并消失,因为您已关闭服务器端的套接字。

通常情况下,您在服务器线程中有某种循环,它正在读取/写入内容,并且只有在您发送"退出"命令,意味着您的客户while-loop在读取第一条消息后不会退出,但我猜这是您刚刚开始玩游戏。

现在,尽管如此,您的客户端代码违反了Swing的单线程特性,有关详细信息,请参阅Concurrency in Swing

您可以通过多种方式解决此问题,但SwingWorker可能是最简单的方法之一,有关详细信息,请参阅Worker Threads and SwingWorker