提问人:Evan Gunawan 提问时间:2/2/2019 更新时间:2/3/2019 访问量:1864
如何阻止Java Socket客户端不断发送“空”数据?
How to stop Java Socket client keeps sending 'null' data?
问:
我创建了 2 个带有套接字的 Java 程序。我希望客户端向服务器发送连续数据。但是在将消息发送到服务器后,客户端会继续向服务器发送“null”值(当我关闭客户端程序中的套接字时会发生这种情况)。 这是我的代码:
import ...
public class MainClient {
private Socket serverSock;
private PrintStream clientOutput;
public static void main(String[] args) {
MainClient client = new MainClient();
client.runClient();
}
public void runClient() {
try {
serverSock = new Socket("127.0.0.1",8282);
clientOutput = new PrintStream(serverSock.getOutputStream());
clientOutput.println("Hello, I'm Connected.");
for (int i=0;i<5;i++) {
clientOutput.println(i + "");
clientOutput.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
// try {
// serverSock.close(); It will keeps sending 'null' data to the server if I use this line.
// } catch (IOException e) {
// e.printStackTrace();
// }
}
}
}
服务器端:
public class MainServer {
private ServerSocket serverSocket;
private int listenPort = 8282;
private InputStream inps;
private Socket clientSocket;
private BufferedReader clientInput;
private MainServer() {
String clientMsg = "";
try {
serverSocket = new ServerSocket(listenPort);
System.out.println("Server is Listening on " + listenPort);
clientSocket = serverSocket.accept();
clientInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while(clientSocket.isConnected()) {
clientMsg = clientInput.readLine();
System.out.println("Client : " + clientMsg);
}
}catch(IOException ex) {
ex.printStackTrace();
}finally {
try {
clientSocket.close();
} catch (IOException e) {}
}
}
public static void main(String[] args) {
new MainServer();
}
}
我试图关闭客户端的 OutputStream,但它在发送 0-4 循环后将 null 发送到服务器。
为了使它停止并避免客户端发送 null 数据,我不应该在客户端上插入 ,但它将返回 SocketException。我希望客户端在完成后发送“已关闭”消息。clientOutput.close();
serverSock.close();
摘要,服务器上的输出为:
Client: 0
Client: 1
Client: 2
Client: 3
Client: 4
Client: null
Client: null
//And so on..
我认为客户端程序中缺少一些东西,我猜? 感谢您的帮助:)
答:
通常,代码应该是类似的
private MainServer() {
String clientMsg = "";
try {
serverSocket = new ServerSocket(listenPort);
System.out.println("Server is Listening on " + listenPort);
clientSocket = serverSocket.accept();
clientInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while ((clientMsg = clientInput.readLine()) != null) {
if(isTerminationString(clientMsg)) {
break;
}
System.out.println("Client : " + clientMsg);
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
}
}
}
boolean isTerminationString(String msg) {
return msg.equals("DONE!");
}
在检查消息是否为终止消息的地方,通信协议应在客户端和服务器之间共享。我举了发送的例子
一个 DONE 消息,但它可能比这更复杂。
由于关闭套接字上的方法并不能保证另一部分上的套接字也会关闭,因此使用该方法可能无效,并导致您遇到的相同问题。isTerminationString
close
isClosed
评论
readLine()
你的 MainClient() 没有问题。
MainServer() 中的 clientSocket.isConnected() 函数始终检查客户端的状态并导致无限循环,因此在消息 'client:4' 之后,clientInput.readLine() 应返回 'null'。
因此,您可以使用函数“clientSocket.isClosed()”来检查客户端套接字是否已连接,而不是检查客户端套接字是否已连接。
将 MainServer() 中的 while 循环替换为以下代码,
while(!clientSocket.isClosed()) {
clientMsg = clientInput.readLine();
System.out.println("Client : " + clientMsg);
if(clientMsg.equals("Closed")){
clientSocket.close();
// serverSocket.close();
}
}
这将帮助您在从服务器接收“已关闭”消息时关闭客户端套接字,从而避免无限执行 while 循环以及 null 语句打印。 代码“serverSocket.close()”可帮助您关闭服务器套接字,如果您需要停止端口侦听,可以在“MainServer()”中使用它。
评论
isConnected()
在服务器中从不检查客户端的状态。 此处既不检测客户端关闭,也不检测“帮助您关闭客户端套接字”。它在这里没有比 更好的工作了。显然你从未尝试过。isClosed()
isConnected()
正如注释所指出的,客户端没有发送值。null
该方法不会做你认为它所做的事情,即它不会告诉你套接字当前是否“连接”到它的对等体,至少以你认为它应该的方式。 一旦套接字转换到连接状态,就会变为 true,此后即使套接字关闭后,它也会保持 true。请参阅此讨论和 stackoverflow 上的其他讨论。isConnected()
isConnected()
确定对等体是否已关闭连接的正确方法是尝试从套接字读取,然后检查结果以查找关闭的证据。请阅读您正在使用的方法的 Javadocs,它们会告诉您各种返回值的含义。对于 BufferedReader.readLine()
方法,它说:
返回值:
一个 String 包含该行的内容,不包括 任何行终止字符,如果流的末尾具有 已达到
Throws:
IOException - 如果发生 I/O 错误
因此,您需要检查 null 返回值以检测正常的套接字闭包,以及是否收到指示某种网络异常的 IOException。
评论
clientInput.readLine()!=null
评论
readLime()