编辑!:我发现了错误,它在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);
}});}}
答案 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