繁体   English   中英

syscall.Sockaddr类型断言

[英]syscall.Sockaddr Type Assertion

我正在打开Linux数据包套接字,并尝试将接收到的数据包读入结构:

type msg struct {
    n, oobn, flags int
    p, oob []byte
    from syscall.Sockaddr
}

socket, err := syscall.Socket(AF_PACKET, SOCK_RAW, ETH_P_ALL)

pkt := new(msg)
pkt.p = make([]byte, 1500)
pkt.oob = make([]byte, 1500)

pkt.n, pkt.oobn, pkt.flags, pkt.from, _ = syscall.Recvmsg(socket, pkt.p, pkt.oob, 0)

根据文档( http://golang.org/pkg/syscall/#Recvmsg ), Recvmsg()将msghdr作为syscall.Sockaddr和上面概述的代码段工作。

打印出pkt.from结构成员,我可以看到在值Sockaddr接口:

fmt.Printf("%+v\n", pkt.from)

>>> &{Protocol:8 Ifindex:3 Hatype:1 Pkttype:0 Halen:6 Addr:[0 0 36 205 126 213 0 0] raw:{Family:0 Protocol:0 Ifindex:0 Hatype:0 Pkttype:0 Halen:0 Addr:[0 0 0 0 0 0 0 0]}}

但是,如果尝试访问它们,则会收到错误消息:

fmt.Println(pkt.from.Ifindex)

>>> pkt.from.Ifindex undefined (type syscall.Sockaddr has no field or method Ifindex)

通过reflect.TypeOf(pkt.from)我发现它的类型为*syscall.SockaddrLinklayer Recvmsg尝试执行分配时,尝试将我的msg struct成员更改为该类型失败,因为它不是syscall.Sockaddr类型。

我能够使用类型断言:

bar := pkt.from.(*syscall.SockaddrLinklayer)
fmt.Println(bar.Ifindex)

>>> 2

我是Go的新手。 这是我的第一种静态类型语言,所以我不明白Recvmsg函数是如何要求 syscall.Sockaddr 但是返回了*syscall.SockaddrLinklayer呢? 我显然缺少了一些非常基本的东西。 另外,使用类型断言是执行此操作的正确方法吗? 感觉真的不对……但是我没有资格做出这样的判断!

Sockaddr是一个接口,因此Recvmsg可以返回满足该接口的不同类型。

有关接口的更多详细信息,请查看Effective Go

您应该检查断言是否有效,这样就不会导致运行时错误,例如:

bar, ok := pkt.from.(*syscall.SockaddrLinklayer) 
if !ok {
    //log error and break out of the loop
}
stuffWith(bar)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM