Golang Raw套接字UDP无法正常工作

时间:2018-04-25 23:17:43

标签: sockets go udp ip packet

主要问题

我正在寻找一种使用go语言发送数据包的方法,这使我能够查看和设置TTL和其他低级别数据包字段(我不需要修改以太网头文件只需ip和UDP头文件)。我试图在下面的代码中制作和发送我自己的数据包。

运行以下代码时,接收方不会收到任何消息。任何人都可以。)警告我在此代码中所做的任何错误或b。)建议使用golang发送udp数据的另一种方法,同时保留对ip和amp;的访问权限。 udp标题?

(我删除了mac地址,需要更换它们才能运行此代码)

代码

(发送)

package main

import (
    "syscall"
    "log"
    "github.com/google/gopacket"
    "github.com/google/gopacket/layers"
    "fmt"
    "encoding/hex"
    "encoding/json"
    "net"
)

type NameTag struct {
    Name string `json:"name"`
}

func main() {
    var err error
    fd, e := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_UDP)
    if e != nil {
        fmt.Println("Problem @ location 1")
    }
    addr := syscall.SockaddrInet4{
        Port: 27289,
        Addr: [4]byte{127, 0, 0, 1},
    }
    p := pkt()
    err = syscall.Sendto(fd, p, 0, &addr)
    if err != nil {
        log.Fatal("Sendto:", err)
    }
}

func pkt() []byte {
    sb := gopacket.NewSerializeBuffer()
    nt := NameTag{"Paul"}
    b, _ := json.Marshal(nt)
    pld := gopacket.Payload(b)
    l := uint16(len(pld))
    udp := layers.UDP{
        SrcPort:  27289,
        DstPort:  27288,
        Length:   l + 8,
        Checksum: 0,
    }
    l = l + 8
    ip := layers.IPv4{
        Version:    0x4,
        IHL:        5,
        Length:     20 + l,
        TTL:        255,
        Flags:      0x40,
        FragOffset: 0,
        Checksum:   0,
        Protocol:   syscall.IPPROTO_UDP,
        DstIP:      net.IPv4(127, 0, 0, 1),
        SrcIP:      net.IPv4(127, 0, 0, 1),
    }
    l = l + 20

    eth := layers.Ethernet{
        EthernetType: layers.EthernetTypeIPv4,
        SrcMAC: net.HardwareAddr{
            0x--, 0x--, 0x--, 0x--, 0x--, 0x--,
        },
        DstMAC: net.HardwareAddr{
            0x--, 0x--, 0x--, 0x--, 0x--, 0x--,
        },
    }
    fmt.Println(pld.SerializeTo(sb, gopacket.SerializeOptions{}))
    fmt.Println(udp.SerializeTo(sb, gopacket.SerializeOptions{}))
    fmt.Println(ip.SerializeTo(sb, gopacket.SerializeOptions{}))
    fmt.Println(eth.SerializeTo(sb, gopacket.SerializeOptions{}))

    //Debug prints here (first line is for dump to packet validator)
    fmt.Println(hex.EncodeToString(sb.Bytes()))
    fmt.Println(sb.Bytes())

    return sb.Bytes()
}

(接收)

package main

import (
    "syscall"
    "os"
    "fmt"
)

func main() {
    fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_UDP)
    if err != nil {
        fmt.Println(err)
        return
    }
    sa:= &syscall.SockaddrInet4{
        Addr: [4]byte{127,0,0,1},
        Port:27288,
    }
    e := syscall.Bind(fd, sa)
    if e != nil {
        fmt.Println("problems @ location 1")
    }
    f := os.NewFile(uintptr(fd), fmt.Sprintf("fd%d", fd))
    fmt.Println("Entering main loop")
    for {
        fmt.Println("In loop")
        buf := make([]byte, 1024)
        numRead, err := f.Read(buf)
        if err != nil {
            fmt.Println("problems @ location 2")
        }
        fmt.Printf("Loop done %v\n", buf[:numRead])
    }

}

0 个答案:

没有答案