【问题标题】:How to demonstrate all the TCP Socket States如何演示所有 TCP 套接字状态
【发布时间】:2015-08-29 07:15:00
【问题描述】:

我试图在使用 Ubuntu 操作系统的笔记本电脑上运行时观察一个简单的 java echo 服务器和客户端程序。为了了解幕后发生的事情,我运行了服务器客户端并使用了这个命令

   sudo netstat -pant 10007

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name

tcp6       0      0 :::10007                :::*                    LISTEN      3551/java          
tcp6       0      0 127.0.0.1:35459         127.0.0.1:10007         ESTABLISHED 3570/java       
tcp6       0      0 127.0.0.1:10007         127.0.0.1:35459         ESTABLISHED 3551/java      

因此,我们可以看到被动服务器(环回)处于 LISTEN 状态,并且在接受客户端(127.0.0.1.35459)套接字后,在 ESTABLISHED 中创建与主动服务器(127.0.0.1.10007)的新 TCP 连接状态。 但是,我们知道有几个TCP Socket状态,例如:SYN_SEND,SYN_RECEIVED,ESTABLISHED,LISTEN,FIN_WAIT_1,TIMED_WAIT,CLOSE_WAIT,FIN_WAIT_2,LAST_ACK,CLOSED等。所以,我对其他状态感到困惑,程序是否正在跳过这些套接字状态与否。

我想查看所有 TCP 套接字状态以了解整个套接字状态转换场景。那么我在哪里做错了?我给了错误的命令吗?或缺少任何代码修改?我缺少任何网络工具吗?我的分步过程出了什么问题?

那么,如何演示所有 TCP 套接字状态?

这是服务器代码:

import java.net.*; 
import java.io.*; 

public class EchoServer 
{ 
 public static void main(String[] args) throws IOException 
   { 
    ServerSocket serverSocket = null; 

    try { 
         serverSocket = new ServerSocket(10007); 
        } 
    catch (IOException e) 
        { 
         System.err.println("Could not listen on port: 10007."); 
         System.exit(1); 
        } 

    Socket clientSocket = null; 
    System.out.println ("Waiting for connection.....");

    try { 
         clientSocket = serverSocket.accept(); 
        } 
    catch (IOException e) 
        { 
         System.err.println("Accept failed."); 
         System.exit(1); 
        } 

    System.out.println ("Connection successful");
    System.out.println ("Waiting for input.....");

    PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), 
                                      true); 
    BufferedReader in = new BufferedReader( 
            new InputStreamReader( clientSocket.getInputStream())); 

    String inputLine; 

    while ((inputLine = in.readLine()) != null) 
        { 
         System.out.println ("Server: " + inputLine); 
         out.println(inputLine); 

         if (inputLine.equals("Bye.")) 
             break; 
        } 

    out.close(); 
    in.close(); 
    clientSocket.close(); 
    serverSocket.close(); 
   } 
} 

这是客户端代码:

import java.io.*;
import java.net.*;

public class EchoClient {
    public static void main(String[] args) throws IOException {

        String serverHostname = new String ("127.0.0.1");

        if (args.length > 0)
           serverHostname = args[0];
        System.out.println ("Attemping to connect to host " +
        serverHostname + " on port 10007.");

        Socket echoSocket = null;
        PrintWriter out = null;
        BufferedReader in = null;

        try {

            echoSocket = new Socket(serverHostname, 10007);
            out = new PrintWriter(echoSocket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(
                                        echoSocket.getInputStream()));
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host: " + serverHostname);
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for "
                               + "the connection to: " + serverHostname);
            System.exit(1);
        }

    BufferedReader stdIn = new BufferedReader(
                                   new InputStreamReader(System.in));
    String userInput;

        System.out.print ("input: ");
    while ((userInput = stdIn.readLine()) != null) {
        out.println(userInput);
        System.out.println("echo: " + in.readLine());
            System.out.print ("input: ");
    }

    out.close();
    in.close();
    stdIn.close();
    echoSocket.close();
    }
}

【问题讨论】:

  • 您必须速度很快,或者以非常低的延迟运行链接。如果网络运行正常,SYN-SENT 和 SYN-RECEIVED 将在一秒钟内转换为 ESTABLISHED,这同样适用于几个关闭阶段。
  • 您需要使用某种限制工具将网络连接速度降低到 10 字节/秒,然后您会看到所有状态。我怀疑事情发生得太快了,您无法观察所有状态。
  • 我无法理解。您能否更具体一点:任何明确的代码或指南或类似链接。
  • 你不明白到底是什么?你有两个 cmets,都清楚地表达了。
  • 我明白 cmets 说什么,但如何让它变慢?需要哪些命令或代码使其变慢?

标签: java sockets tcp


【解决方案1】:

这里的问题是,操作系统会处理状态。您不能简单地从 Java 控制 L4 协议。如果您想这样做,则必须在 linux RAW 套接字上实现自己的 TCP 堆栈(也许已经有实现,还没有查看)。

因此,让操作系统处理状态并使用环回进行测试,您的状态将具有几微秒的生命周期。 (实际上,当两端都在同一台机器上并且不涉及实际网络时,我相信现代 linux 甚至会跳过其中的一些。)我会说尝试通过 netstat 查看状态对于理解 TCP 的方式几乎没有价值。有效。

我建议你看看Wikipedia TCP page。它很好地描述了所有状态,并且有很好的图表来描述状态转换。

如果您想查看“在线”发生了什么,我建议您尝试任一 tcpdump。 tcpdump -n -i lo port 10007(有关更多用法、更详细的输出等,请参见手册页)或 GUI 应用程序 Wireshark。 Wireshark 对你来说可能是更好的选择,因为它可以很好地剖析数据包并且几乎可以解释每一点。

(其实tcpdump可以用来抓包到文件——使用-w file标志,稍后在Wireshark中打开。)

【讨论】:

  • 在您发表评论后,我现在很清楚了。但是仍然可以在特定的套接字连接和端口上检索 tcp 数据包(我猜 tcp 数据包包含:SYN 标志、ACK 标志、FIN 标志等),然后我可以很容易地得到一些关于后面发生的事情的替代解释。所以,你知道任何命令吗(例如:netstat 等)?
  • @user5005768 我更新了答案...希望对您有所帮助。
猜你喜欢
  • 2014-01-31
  • 2011-01-31
  • 2023-03-19
  • 2018-08-01
  • 1970-01-01
  • 2014-02-08
  • 2014-09-01
  • 2012-05-04
  • 1970-01-01
相关资源
最近更新 更多