我打开一个Linux包套接字,并尝试阅读收到的数据包成一个结构:syscall.Sockaddr类型断言
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
和代码段我上面列出的作品。然而
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]}}
,如果我尝试访问它们,我得到一个错误:
打印出pkt.from
结构成员,我可以看到的值在Sockaddr
接口
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
结构成员更改为该类型,因为它不是syscall.Sockaddr
类型。
我能够使用类型断言:
bar := pkt.from.(*syscall.SockaddrLinklayer)
fmt.Println(bar.Ifindex)
>>> 2
我很新的地方;这是我的第一个静态类型的语言,所以我不明白如何Recvmsg
func是需要 a syscall.Sockaddr
但返回*syscall.SockaddrLinklayer
?我显然错过了一些非常基本的东西。此外,正在使用类型断言正确的方式来做到这一点?这并不是真的感觉正确......但我并不真的有资格做出这样的判断!
确定 - 这是有道理的。使用类型断言“正确”的方式来读取这些数据? – tMC 2014-09-03 23:22:00
@tMC是的,但你必须确保它是有效的,我添加了一个小例子。 – OneOfOne 2014-09-03 23:27:01