我写了一个客户端,它基本上只是打开一个套接字并通过连接发送内容。 (内容遵循Http协议)
我面临的问题是关于如何以及何时关闭连接的问题。 问题是连接有时太早关闭(" FIN"在服务器应答之前发送到服务器)。
在这种情况下,服务器的答案丢失了 我尝试在关闭连接之前使用Thread.sleep,但似乎没有任何因素影响内容发送和" FIN"之间的时间。邮件已发送。 (在Wireshark中查看)
答案有时会到来,有时候不会(比赛条件)。
我如何延迟" FIN"消息,所以我不会错过服务器的回复?
我添加了相关课程。相关函数是sendContentOverSocket
public class SocketClient {
private String hostName;
private int portNumber;
private Socket ConnectionSocket;
public void init(String hostName, int portNumber){
this.hostName = hostName;
this.portNumber = portNumber;
this.ConnectionSocket=createSocketConnection();
}
private Socket createSocketConnection() {
Socket socket = null;
try {
socket = new Socket(this.hostName, this.portNumber);
return socket;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return socket;
}
public void sendContentOverSocket(String content) {
try {
PrintWriter out = new PrintWriter(
ConnectionSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(
ConnectionSocket.getInputStream()));
out.print(content);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.close();
in.close();
ConnectionSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:0)
TCP使用称为半关闭的概念。 当您关闭套接字时,表明您将不再发送。 在您的解释中,我看到“在服务器应答之前将FIN发送到服务器”,如果您是客户端,则意味着您已在套接字上执行了关闭。 如果您期望在特定时间范围内来自服务器的结果,则需要某种计时机制,可能会将select与超时结合使用。 如果服务器关闭了他的连接结束,则通过接收接收中的字节来检测此情况。通常这意味着您也必须关闭套接字。 总而言之,关闭套接字有三个原因:
答案 1 :(得分:0)
当然,您应该在阅读回复后关闭连接。很难在这里看到这个谜。没睡觉。如果您没有阅读响应(a),则无法知道请求是成功还是失败,以及(b)服务器也有可能遇到异常。
您的代码质量很差。所有这些方法都应该传播异常,而不是在内部捕获它们并返回null。
答案 2 :(得分:0)
对于Java 7,由于所有三个类,即Socket,PrintWriter,BufferedReader,都实现AutoCloseable,并根据事实,您要关闭调用sendContentOverSocket(String content)
后立即尝试使用以下代码:
public class SocketClient {
private String hostName;
private int portNumber;
public void init(String hostName, int portNumber) {
this.hostName = hostName;
this.portNumber = portNumber;
}
public void sendContentOverSocket(String content) {
try (Socket socket = new Socket(this.hostName, this.portNumber);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
out.print(content);
} catch(IOException e) {
//Appropriate exception handler
}
}
}
在这种情况下,Java将自行正确关闭所有资源。
如果您使用Java 6或更早版本,请尝试使用try-finally阻止:
答案 3 :(得分:0)
解决。
我现在明白它是如何运作的。 我在客户端中缺少的是尝试从输入流中读取。 当你尝试阅读
while ((inputFromServer = in.readLine()) != null)
客户端等待输入。唯一会打破这个循环的是关闭连接的服务器。
在此之后,您可以安全地关闭客户端上的连接。无需延迟FIN等......