在Linux 网络编程中,有两个函数,- #include <sys/types.h> /* See NOTES */
- #include <sys/socket.h>
- int getsockopt(int sockfd, int level, int optname,
- void *optval, socklen_t *optlen);
- int setsockopt(int sockfd, int level, int optname,
- const void *optval, socklen_t optlen);
以上两个函数使用来设置以及获得socket中的一些选项。这两个函数的参数中的scokfd制定的是需要操作的socket,而optname指定的是操作所面向的选项名称,optval以及optlen则是对所获的内容/所设置内容的一个描述。而level之前则一直没有办法理解,今天在看了一段代码之后就豁然开朗了。
level在通常的时候使用SOL_SOCKET用来制定对应的对应的相关操作,如之前博客所涉及到的sndbuf大小。
今天在看UDP实现的时候发现UDP中对应setsockopt对应的代码如下:
- int udp_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, unsigned int optlen)
- {
- if (level == SOL_UDP || level == SOL_UDPLITE)
- return udp_lib_setsockopt(sk, level, optname, optval, optlen,
- udp_push_pending_frames);
- return ip_setsockopt(sk, level, optname, optval, optlen);
- }
通过此段代码我就明白了level的意思,当level是属于SOL_UDP时,则进行UDP协议专属的一些设置属性操作,如果不是的话,那么则应当是UDP所依赖的IP协议,则调用ip_setsockopt。
通过了level这个参数,使用统一个接口函数能够设置不同协议的属性。当设置为SOL_SOCKET时表示的是socket通用的属性,那么不需要涉及具体的协议,可以直接搞定。如果涉及到具体的协议,如TCP/UDP则需要指定level为对应的值。这个可以通过setsockopt的内核中系统调用的入口能够看到。
- SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
- char __user *, optval, int, optlen)
- {
- int err, fput_needed;
- struct socket *sock;
- if (optlen < 0)
- return -EINVAL;
- sock = sockfd_lookup_light(fd, &err, &fput_needed);
- if (sock != NULL) {
- err = security_socket_setsockopt(sock, level, optname);
- if (err)
- goto out_put;
- if (level == SOL_SOCKET)
- err =
- sock_setsockopt(sock, level, optname, optval,
- optlen);
- else
- err =
- sock->ops->setsockopt(sock, level, optname, optval,
- optlen);
- out_put:
- fput_light(sock->file, fput_needed);
- }
- return err;
- }
这个函数中,首先是根据level是否等于SOL_SOCKET来确定对应的服务函数,如果为SOL_SOCKET那么直接调用sock_setsockopt函数来解决,因为在struct sock这个层次就能够解决此问题,如果不是这个level那么说明需要对应具体的协议,那么就调用对应协议的setsockopt实现来实现。
阅读(2709) | 评论(0) | 转发(0) |