1. 程式人生 > 其它 >程式碼&抓包看SOCKET通訊的過程

程式碼&抓包看SOCKET通訊的過程

技術標籤:從Socket到Nettyjavasockettcpdump

測試環境

10.188.40.230 部署SocketServer

10.188.40.231 部署SocketClient

JDK環境:jdk8

執行程式碼

Server端


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;


public class SocketServer {

    public static void main(String[] args) {

        ServerSocket server = null;
        try {
            server = new ServerSocket();
            server.bind(new InetSocketAddress(9090), 20);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("server up use 9090!");
        try {
            while (true) {

                Socket client = server.accept();
                new Thread(
                        () -> {
                            try {
                                InputStream in = client.getInputStream();
                                BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                                while(true){
                                String dataline = reader.readLine();
                                if(null != dataline){
                                    System.out.println(dataline);
                                }else{
                                    client.close();
                                    break;
                                    }
                                }
                           } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                ).start();

            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                server.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

Client端


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

public class SocketClient {

    public static void main(String[] args) {

        try {
            Socket client = new Socket("10.188.40.230",9090);
            OutputStream out = client.getOutputStream();
            InputStream in = System.in;
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            while(true){
                String line = reader.readLine();
                if(line != null ){
                    byte[] bb = line.getBytes();
                    for (byte b : bb) {
                        out.write(b);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

抓包過程

1,啟動SocketServer

2,程式碼執行到server.accecpt()阻塞

此時lsof -p pid 檢視fd,發現fd5 處於LISTEN狀態

java    17046 sftcwl    5u  IPv6            3865306       0t0       TCP *:websm (LISTEN)

3,啟動SocketClient

SocketServer接收到一個連線,核心完成三次握手

抓包命令

tcpdump -nn -i lo port 9090
21:32:17.553914 IP 10.188.40.231.41758 > 10.188.40.230.9090: Flags [S], seq 4066755135, win 29200, options [mss 1460,sackOK,TS val 1698174967 ecr 0,nop,wscale 7], length 0
21:32:17.553966 IP 10.188.40.230.9090 > 10.188.40.231.41758: Flags [S.], seq 3584360549, ack 4066755136, win 1152, options [mss 1460,sackOK,TS val 2199546408 ecr 1698174967,nop,wscale 0], length 0
21:32:17.554209 IP 10.188.40.231.41758 > 10.188.40.230.9090: Flags [.], ack 1, win 229, options [nop,nop,TS val 1698174968 ecr 2199546408], length 0

再檢視fd,fd6 ESTABLISHED 與Client已經建立了連線

java    17046 sftcwl    6u  IPv6            3865476       0t0       TCP root:websm->10.188.40.231:41758 (ESTABLISHED)

4,Client傳送資料

21:35:09.429392 IP 10.188.40.231.41758 > 10.188.40.230.9090: Flags [P.], seq 1:2, ack 1, win 229, options [nop,nop,TS val 1698346843 ecr 2199546408], length 1
21:35:09.429460 IP 10.188.40.230.9090 > 10.188.40.231.41758: Flags [.], ack 2, win 1152, options [nop,nop,TS val 2199718284 ecr 1698346843], length 0
21:35:09.429653 IP 10.188.40.231.41758 > 10.188.40.230.9090: Flags [P.], seq 2:4, ack 1, win 229, options [nop,nop,TS val 1698346843 ecr 2199718284], length 2
21:35:09.430096 IP 10.188.40.230.9090 > 10.188.40.231.41758: Flags [.], ack 4, win 1152, options [nop,nop,TS val 2199718285 ecr 1698346843], length 0

Strace追蹤系統呼叫

strace用於追蹤系統呼叫

strace -ff -o out /bin/java SocketClient

能夠看到很多個out檔案,每個out檔案代表一個執行緒

在主執行緒的out檔案中能看到以下系統呼叫

socket(AF_INET6, SOCK_STREAM, IPPROTO_IP) = 5
setsockopt(5, SOL_IPV6, IPV6_V6ONLY, [0], 4) = 0
bind(5, {sa_family=AF_INET6, sin6_port=htons(9090), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, 28) = 0
listen(5, 20)
poll([{fd=5, events=POLLIN|POLLERR}], 1, -1) = 1 ([{fd=5, revents=POLLIN}])
accept(5, {sa_family=AF_INET6, sin6_port=htons(34972), inet_pton(AF_INET6, "::ffff:10.188.40.230", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, [28]) = 6