Wireshark+Go捕获本地TCP通信

初学计网,使用Wireshark观察本地端口间TCP通信过程。

目录

步骤1:

步骤2:

步骤3:

步骤1:

使用go语言搭建本地客户端与服务器TCP通信,测试完成后在步骤2先运行服务器,再运行客户端。

服务器:端口为20000

package main

import (
	"bufio"
	"fmt"
	"net"
	"os"
	"strings"
)

// TCP 服务端
func process(conn net.Conn) {
	// 函数执行完之后关闭连接
	defer conn.Close()
	// 输出主函数传递的conn可以发现属于*TCPConn类型, *TCPConn类型那么就可以调用*TCPConn相关类型的方法, 其中可以调用read()方法读取tcp连接中的数据
	fmt.Printf("服务端: %T\n", conn)
	for {
		var buf [128]byte
		// 将tcp连接读取到的数据读取到byte数组中, 返回读取到的byte的数目
		n, err := conn.Read(buf[:])
		if err != nil {
			// 从客户端读取数据的过程中发生错误
			fmt.Println("read from client failed, err:", err)
			break
		}

		recvStr := string(buf[:n])
		fmt.Println("服务端收到客户端发来的数据:", recvStr)
		// 由于是tcp连接所以双方都可以发送数据, 下面接收服务端发送的数据这样客户端也可以收到对应的数据
		inputReader := bufio.NewReader(os.Stdin)
		s, _ := inputReader.ReadString('\n')
		t := strings.Trim(s, "\r\n")
		// 向当前建立的tcp连接发送数据, 客户端就可以收到服务端发送的数据
		conn.Write([]byte(t))
	}
}

func main() {
	// 监听当前的tcp连接
	listen, err := net.Listen("tcp", "127.0.0.1:20000")
	fmt.Printf("服务端: %T=====\n", listen)
	fmt.Printf("服务器端地址为: ")
	fmt.Println(listen.Addr())
	if err != nil {
		fmt.Println("listen failed, err:", err)
		return
	}
	for {
		conn, err := listen.Accept() // 建立连接
		fmt.Println("当前建立了tcp连接")
		if err != nil {
			fmt.Println("accept failed, err:", err)
			continue
		}
		// 对于每一个建立的tcp连接使用go关键字开启一个goroutine处理
		go process(conn)
	}
}

客户端,端口每次运行时随机分配

package main

import (
	"bufio"
	"fmt"
	"net"
	"os"
	"strings"
)

func main() {
	// 连接到服务端建立的tcp连接
	conn, err := net.Dial("tcp", "127.0.0.1:20000")
	// 输出当前建Dial函数的返回值类型, 属于*net.TCPConn类型
	fmt.Printf("客户端: %T\n", conn)
	fmt.Printf("客户端地址为: ")
	fmt.Println(conn.LocalAddr())
	if err != nil {
		// 连接的时候出现错误
		fmt.Println("err :", err)
		return
	}
	// 当函数返回的时候关闭连接
	defer conn.Close()
	// 获取一个标准输入的*Reader结构体指针类型的变量
	inputReader := bufio.NewReader(os.Stdin)
	for {
		// 调用*Reader结构体指针类型的读取方法
		input, _ := inputReader.ReadString('\n') // 读取用户输入
		// 去除掉\r \n符号
		inputInfo := strings.Trim(input, "\r\n")
		// 判断输入的是否是Q, 如果是Q则退出
		if strings.ToUpper(inputInfo) == "Q" { // 如果输入q就退出
			return
		}
		_, err = conn.Write([]byte(inputInfo)) // 发送数据
		if err != nil {
			return
		}
		buf := [512]byte{}
		// 读取服务端发送的数据
		n, err := conn.Read(buf[:])
		if err != nil {
			fmt.Println("rev failed, err:", err)
			return
		}
		fmt.Println("客户端接收服务端发送的数据: ", string(buf[:n]))
	}
}

步骤2:

打开Wireshark软件,并在捕获选项中选择:adpter for lookback traffic capture

 进入捕获后通过命令 tcp.port == 服务器端口 (本文为20000) 进行捕获

 接着,运行服务器,再运行客户端,以下是三次握手:

 每过一段时间,基于连接的TCP协议双方都会发送心跳消息报进行确认:

但我还没弄明白 TCP Keep-Alive与 TCP Dup ACK的区别 ,于是查看了以下文章:

 TCP报文( tcp dup ack 、TCP Retransmission)_tcp fast retransmission_ynchyong的博客-CSDN博客

步骤3:

接着,我通过客户端向服务器发送了一条 110110110的数字序列,wireshark完美捕获并解析了这条信息。

附带消息的Len一般大于 1 byte 

解析结果:

 随后我在三个110中间添加了两个空格,wireshark并不能正常解析出字节流所对应的数据,这说明我的操作方式只能对明文进行捕获,加密信息只能捕获字节流。

最后,为了展示双方进行四次挥手,修改了客户端代码,使得三次握手与四次挥手不被心跳包间隔,以便观察:

修改后的客户端代码:

package main

import (
	"fmt"
	"net"
	"strings"
)

func main() {
	// 连接到服务端建立的tcp连接
	conn, err := net.Dial("tcp", "127.0.0.1:20000")
	// 输出当前建Dial函数的返回值类型, 属于*net.TCPConn类型
	fmt.Printf("客户端: %T\n", conn)
	fmt.Printf("客户端地址为: ")
	fmt.Println(conn.LocalAddr())
	if err != nil {
		// 连接的时候出现错误
		fmt.Println("err :", err)
		return
	}
	// 当函数返回的时候关闭连接
	// 获取一个标准输入的*Reader结构体指针类型的变量
	for true {
		// 调用*Reader结构体指针类型的读取方法
		var s string
		_, err := fmt.Scan(&s)
		if err != nil {
			return
		}
		if s == "quit" {
			err := conn.Close()
			if err != nil {
				return
			}
		}
		// 去除掉\r \n符号
		inputInfo := strings.Trim(s, "\r\n")
		// 判断输入的是否是Q, 如果是Q则退出
		if strings.ToUpper(inputInfo) == "Q" { // 如果输入q就退出
			return
		}
		_, err = conn.Write([]byte(inputInfo)) // 发送数据
		if err != nil {
			return
		}
		buf := [512]byte{}
		// 读取服务端发送的数据
		n, err := conn.Read(buf[:])
		if err != nil {
			fmt.Println("rev failed, err:", err)
			return
		}
		fmt.Println("客户端接收服务端发送的数据: ", string(buf[:n]))
	}
}

需要注意的是,在重启客户端时得重新进行捕获以刷新记录。

通过Ref 3 可以识别挥手过程是哪几个通信

References

  WireShark 抓包使用教程--详细_HarveyH的博客-CSDN博客

 Go语言实现TCP通信_go tcp_yuzhang_zy的博客-CSDN博客

一文彻底搞懂 TCP三次握手、四次挥手过程及原理 - 知乎 (zhihu.com)

 WireShark抓包分析_hebbely的博客-CSDN博客

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七月是你的谎言..

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值