[英]manage socket connection in Java over tcp
我写了一个客户端,基本上只打开一个套接字并通过连接发送内容。 (内容遵循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();
}
}
}
TCP使用称为半封闭的概念。 当您关闭套接字时,这表示您将不再发送。 在您的解释中,我看到“在服务器应答之前先将FIN发送到服务器”,如果您是客户端,则意味着您已对套接字执行了关闭操作。 如果您希望服务器在特定时间内得到结果,则需要某种计时机制,可能将select与超时结合使用。 如果服务器关闭其连接的末端,则可以通过接收receive中的字节来检测到这一点。 通常,这意味着您也必须关闭插座。 因此,总而言之,有3个原因可以关闭插座:
当然,您应该在阅读响应后关闭连接。 很难在这里看到这个谜。 没睡 如果您不阅读响应(a)您将无法知道请求是成功还是失败,以及(b)服务器也有可能遇到异常。
您的代码质量很差。 所有这些方法都应传播异常,而不是在内部捕获异常并返回null。
对于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块代替:
解决了。
我现在了解它是如何工作的。 我在客户端中缺少的是尝试从输入Stream读取的内容。 当您尝试阅读时
while ((inputFromServer = in.readLine()) != null)
客户端等待输入。 唯一会打破此循环的是服务器关闭连接。
之后,您可以安全地在客户端上关闭连接。 无需延迟FIN等
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.