简体   繁体   English

syscall.Sockaddr类型断言

[英]syscall.Sockaddr Type Assertion

I am opening a Linux packet socket and trying to read received packets into a struct: 我正在打开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)

Per the documentation ( http://golang.org/pkg/syscall/#Recvmsg ) Recvmsg() returns the msghdr as a syscall.Sockaddr and the code pieces I've outlined above works. 根据文档( http://golang.org/pkg/syscall/#Recvmsg ), Recvmsg()将msghdr作为syscall.Sockaddr和上面概述的代码段工作。

Printing out the pkt.from struct member, I can see the values in the Sockaddr interface: 打印出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]}}

However, if I try to access them, I get an error: 但是,如果尝试访问它们,则会收到错误消息:

fmt.Println(pkt.from.Ifindex)

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

Via reflect.TypeOf(pkt.from) I found it was of type *syscall.SockaddrLinklayer . 通过reflect.TypeOf(pkt.from)我发现它的类型为*syscall.SockaddrLinklayer Trying to change my msg struct member to that type fails when Recvmsg tries to do the assignment since it not of type syscall.Sockaddr . Recvmsg尝试执行分配时,尝试将我的msg struct成员更改为该类型失败,因为它不是syscall.Sockaddr类型。

I was able to use a type assertion: 我能够使用类型断言:

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

>>> 2

I'm very new to Go; 我是Go的新手。 it is my first statically typed language so I don't understand how the Recvmsg func is requiring a syscall.Sockaddr but returning a *syscall.SockaddrLinklayer ? 这是我的第一种静态类型语言,所以我不明白Recvmsg函数是如何要求 syscall.Sockaddr 但是返回了*syscall.SockaddrLinklayer呢? I'm clearly missing something very fundamental. 我显然缺少了一些非常基本的东西。 Also, is using the type assertion the correct way to do this? 另外,使用类型断言是执行此操作的正确方法吗? It doesn't really feel right... but I'm not really qualified to make such judgments! 感觉真的不对……但是我没有资格做出这样的判断!

Sockaddr is an interface, so Recvmsg can return different types that fulfill that interface. Sockaddr是一个接口,因此Recvmsg可以返回满足该接口的不同类型。

For more details about interfaces check Effective Go . 有关接口的更多详细信息,请查看Effective Go

You should check if the assertion is valid or not so you wouldn't end up with a runtime error, for example: 您应该检查断言是否有效,这样就不会导致运行时错误,例如:

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