程式碼&抓包看SOCKET通訊的過程
阿新 • • 發佈:2020-12-14
技術標籤:從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