跳转至
阅读量:

Go IP 套接字编程

ICMP 监听

package main

import (
    "fmt"
    "net"

    "golang.org/x/net/icmp"
)

func main() {
    // 这里的ipv4地址是指该程序运行的操作系统的网卡地址
    netaddr, _ := net.ResolveIPAddr("ip4", "127.0.0.1")
    // 这里可以指定"网络层协议:子协议"参数,前者可以取ip4/ip6,后者主要有icmp/igmp/tcp/udp/ipv6/icmp
    conn, _ := net.ListenIP("ip4:icmp", netaddr)
    for {
        buf := make([]byte, 1024)
        n, addr, _ := conn.ReadFrom(buf)
        msg, _ := icmp.ParseMessage(1, buf[0:n])
        fmt.Println(n, addr, msg.Type, msg.Code, msg.Checksum)
    }
}

TCP 监听

package main

import (
    "bytes"
    "encoding/binary"
    "fmt"
    "net"
)

func main() {
    netaddr, _ := net.ResolveIPAddr("ip4", "172.17.0.3")
    // 注意,这里修改了监听协议
    conn, _ := net.ListenIP("ip4:tcp", netaddr)
    for {
        // 缓冲区大小和TCP包大小匹配
        buf := make([]byte, 1480)
        n, addr, _ := conn.ReadFrom(buf)
        // 这里用别人写好的函数解析了一下TCP首部,默认20字节
        tcpheader := NewTCPHeader(buf[0:n])
        fmt.Println(n, addr, tcpheader)
    }
}

/*
Copyright 2013-2014 Graham King
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License (GPLv3)
*/

type TCPHeader struct {
    Source      uint16
    Destination uint16
    SeqNum      uint32
    AckNum      uint32
    DataOffset  uint8 // 4 bits
    Reserved    uint8 // 3 bits
    ECN         uint8 // 3 bits
    Ctrl        uint8 // 6 bits
    Window      uint16
    Checksum    uint16 // Kernel will set this if it's 0
    Urgent      uint16
}

// Parse packet into TCPHeader structure
func NewTCPHeader(data []byte) *TCPHeader {
    var tcp TCPHeader
    r := bytes.NewReader(data)
    binary.Read(r, binary.BigEndian, &tcp.Source)
    binary.Read(r, binary.BigEndian, &tcp.Destination)
    binary.Read(r, binary.BigEndian, &tcp.SeqNum)
    binary.Read(r, binary.BigEndian, &tcp.AckNum)

    var mix uint16
    binary.Read(r, binary.BigEndian, &mix)
    tcp.DataOffset = byte(mix >> 12)  // top 4 bits
    tcp.Reserved = byte(mix >> 9 & 7) // 3 bits
    tcp.ECN = byte(mix >> 6 & 7)      // 3 bits
    tcp.Ctrl = byte(mix & 0x3f)       // bottom 6 bits

    binary.Read(r, binary.BigEndian, &tcp.Window)
    binary.Read(r, binary.BigEndian, &tcp.Checksum)
    binary.Read(r, binary.BigEndian, &tcp.Urgent)

    return &tcp
}

func (tcp *TCPHeader) String() string {
    if tcp == nil {
        return "<nil>"
    }
    return fmt.Sprintf("Source=%v Destination=%v SeqNum=%v AckNum=%v DataOffset=%v Reserved=%v ECN=%v Ctrl=%v Window=%v Checksum=%v Urgent=%v", tcp.Source, tcp.Destination, tcp.SeqNum, tcp.AckNum, tcp.DataOffset, tcp.Reserved, tcp.ECN, tcp.Ctrl, tcp.Window, tcp.Checksum)
}

评论