Wireshark学TCP

1.环境准备

go语言准备一个server和一个client

1.1 server

go 复制代码
package main

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

func handleConnection(conn net.Conn) {
    defer conn.Close()
    fmt.Printf("客户端已连接: %s\n", conn.RemoteAddr())

    reader := bufio.NewReader(conn)
    for {
       // 读取客户端消息
       message, err := reader.ReadString('\n')
       if err != nil {
          fmt.Println("连接断开:", err)
          return
       }

       // 处理消息
       message = strings.TrimSpace(message)
       fmt.Printf("收到来自 %s 的消息: %s\n", conn.RemoteAddr(), message)

       // 发送响应
       response := fmt.Sprintf("已收到你的消息(%d字节)\n", len(message))
       _, err = conn.Write([]byte(response))
       if err != nil {
          fmt.Println("发送响应失败:", err)
          return
       }
    }
}

func main() {
    // 监听8080端口
    listener, err := net.Listen("tcp", ":8080")
    if err != nil {
       fmt.Println("监听失败:", err)
       return
    }
    defer listener.Close()
    fmt.Println("服务器已启动,正在监听 :8080 端口...")

    for {
       // 等待客户端连接
       conn, err := listener.Accept()
       if err != nil {
          fmt.Println("接受连接失败:", err)
          continue
       }

       // 为每个连接创建goroutine
       go handleConnection(conn)
    }
}

client

go 复制代码
package main

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

func main() {
    // 连接服务器
    conn, err := net.Dial("tcp", "localhost:8080")
    if err != nil {
       fmt.Println("连接服务器失败:", err)
       return
    }
    defer conn.Close()
    fmt.Println("已连接到服务器")

    // 创建读写器
    reader := bufio.NewReader(os.Stdin)
    connReader := bufio.NewReader(conn)

    for {
       // 读取用户输入
       fmt.Print("请输入消息(输入exit退出): ")
       message, _ := reader.ReadString('\n')
       message = strings.TrimSpace(message)

       if message == "exit" {
          fmt.Println("退出客户端")
          return
       }

       // 发送消息到服务器
       _, err := conn.Write([]byte(message + "\n"))
       if err != nil {
          fmt.Println("发送消息失败:", err)
          return
       }

       // 接收服务器响应
       response, err := connReader.ReadString('\n')
       if err != nil {
          fmt.Println("读取响应失败:", err)
          return
       }

       fmt.Printf("服务器响应: %s", response)
    }
}

2.记一点简单的理论

2.1 三次握手

2.2 标识符

3.wireshark实践

双击打开第一个tcp 使用本地的adapter loop

1.字节和图像是对应的

一个字节=8bit=两个十六位数=255

65个字节

1. 标识源端口

2. 标识目标端口

3.标识序列号(以及显示一个相对序列号)

4. 标识确认号

5.标识flags

6.8+24bit构成两个字节

1.tcp头部长度 4bit
  • ​官方名称​ ​:Data Offset(数据偏移量)。

  • ​作用​ ​:指示TCP头部的总长度(单位:​​4字节​​),以便接收方知道头部结束、数据部分开始的位置。

    • 例如:Data Offset=5 → 头部长度 = 5 × 4 = 20字节(标准TCP头部的最小长度)。头部一定是4字节的倍数

后面的是保留字段

2.flags 12bit

7.窗口大小

8.校验和

  • 计算范围​ :覆盖 ​TCP伪头部 + TCP头部 + TCP数据​(校验和字段本身除外)。
  • ​验证方式​ :接收方重新计算校验和,若与包中的 Checksum 值不匹配,则丢弃该包。

校验和覆盖以下三部分数据(按顺序拼接):

  1. ​IPv6伪头部​(Pseudo-Header):增强校验强度,包含IP层关键信息。
  2. ​TCP头部​ :包括所有字段(但校验和字段本身需置为 0x0000)。
  3. ​TCP数据​:即有效载荷(Payload)。

计算反码和​

  1. ​按16位分组​:将所有数据(伪头部 + TCP头部 + 数据)按16位(2字节)分割。
  2. ​累加所有16位字​:若累加结果超过16位(溢出),将溢出部分(进位)加到低位。
  3. ​取反码​:对最终累加结果按位取反(1→0,0→1)。

9.紧急指针

紧急指针的作用​

  • ​定义​ :当 TCP 标志位中的 ​URG (Urgent)​ 被置为 1 时,Urgent Pointer 表示​紧急数据​的位置(偏移量)。
  • ​目的​ :允许接收方优先处理某些关键数据(如终端命令 Ctrl+C 中断操作),即使正常数据未被全部接收

flags有一个Urgent的标志位

10 应用层数据

相关推荐
搬码临时工9 小时前
使用自定义固定公网URL地址远程访问公司内网OA办公系统,本地无需公网IP和专线让外网访问
网络·网络协议·tcp/ip
sheepwjl13 小时前
《嵌入式硬件(三):串口通信》
网络·嵌入式硬件·网络协议·串口通信
noravinsc13 小时前
RPC和HTTP的区别?
网络协议·http·rpc
XMYX-016 小时前
解决 Apache/WAF SSL 证书链不完整导致的 PKIX path building failed 问题
网络协议·apache·ssl
XXYBMOOO16 小时前
Qt UDP 通信类详解与实现
开发语言·网络·c++·qt·网络协议·ui·udp
dog25017 小时前
乐观并发: TCP 与编程实践
网络·网络协议·tcp/ip
计算机毕设定制辅导-无忧学长20 小时前
MQTT 认证与授权机制实践(二)
网络协议
Jayyih1 天前
嵌入式系统学习Day30(udp)
网络协议·学习·udp
耐达讯通信技术1 天前
耐达讯自动化RS485与Profinet双向奔赴,伺服驱动器连接“稳稳拿捏”
运维·人工智能·物联网·网络协议·自动化·信息与通信
耐达讯通信技术1 天前
嘎嘎厉害!耐达讯自动化RS485转Profinet网关就是食品温控的“天选之子”
运维·服务器·网络·人工智能·网络协议·自动化·信息与通信