Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过tcp管理Java中的套接字连接_Java_Sockets_Tcp_Tcpclient - Fatal编程技术网

通过tcp管理Java中的套接字连接

通过tcp管理Java中的套接字连接,java,sockets,tcp,tcpclient,Java,Sockets,Tcp,Tcpclient,我写了一个客户端,它基本上只是打开一个套接字并通过连接发送内容。(内容遵循Http协议) 我面临的问题是关于这个问题——我应该如何以及何时关闭连接。 问题是连接有时关闭得太早(“FIN”在服务器应答之前发送到服务器) 在这种情况下,服务器的答案将丢失。 我试图在关闭连接之前使用Thread.sleep,但似乎没有任何东西影响发送内容和发送“FIN”消息之间的时间。(在Wireshark中查看) 答案有时到达,有时不到达(比赛条件) 如何延迟“FIN”消息,以避免错过服务器的响应 我添加了相关的类

我写了一个客户端,它基本上只是打开一个套接字并通过连接发送内容。(内容遵循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和超时。 如果服务器关闭其连接端,您可以通过接收接收中的字节来检测。通常这意味着您也必须关闭插座。 因此,总而言之,关闭插座有三个原因:

  • 服务器关闭了套接字的一端,基本上说我不再发送了
  • 您已经等待了一段时间,已经厌倦了等待,决定自己关闭插座
  • 任何其他错误条件,但通常它们都显示为接收0字节或负数

    • 当然,您应该在阅读响应后关闭连接。很难看出这里的奥秘。不睡觉。如果您没有读取响应(a)您无法知道请求是否成功,以及(b)服务器也可能遇到异常


      你的代码质量很差。所有这些方法都应该传播异常,而不是在内部捕获异常并返回null。

      对于Java 7,因为所有三个类(即)都实现并基于这样一个事实,即您希望在调用
      sendContentOverSocket(字符串内容)
      后立即关闭套接字。请尝试使用以下代码:

          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或更早版本,请尝试改用block:

      已解决

      我现在明白它是如何工作的了。 我在客户端缺少的是尝试从输入流读取数据。 当你尝试阅读时

      while ((inputFromServer = in.readLine()) != null)
      
      客户端等待输入。唯一能打破这个循环的是服务器关闭连接


      之后,您可以安全地关闭客户端的连接。无需延迟FIN等…

      @user1274820套接字不会“错误关闭”,除非您做错了什么。谢谢,但我如何“等待一段时间”?我尝试在发送消息后和关闭连接前使用sleep,但效果不理想。您可以在wireshark映像中看到,睡眠(出于某种原因)是在Http之前执行的,而不是在发送FIN之前执行的。您应该使用select api。您可以使用套接字上的readset进行选择,并指定一个10秒的超时。如果套接字上有可用数据或发生超时,选择将返回。如果是超时,则关闭套接字。或者更确切地说,由于这是一个
      套接字,
      使用
      setSoTimeout()
      设置读取超时并捕获结果<代码>SocketTimeoutException。这只是一个简单的问题示例。异常处理得到处理。谢谢