今天我就来唠唠这个 setsockopt
,当初弄这个玩意儿可把我折腾得够呛。我记得那天,我正埋头写一个网络程序,需要对套接字做一些精细化的控制,比如设置超时时间、开启地址复用之类的。我觉得这还不简单?不就是调用几个函数的事儿嘛结果,现实狠狠地给我一巴掌。
我先是翻一堆资料,发现 setsockopt
这个函数可以用来设置套接字的各种选项。资料上写得挺简单的:“setsockopt()
函数用于任意类型、任意状态套接口的设置选项值”。我心想这不就得,直接调用就完事儿!于是我兴冲冲地开始写代码:
创建一个 socket:
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
然后直接调用 setsockopt 函数:
int ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char)&on, sizeof(on));
s
:就是我刚刚创建的那个套接字的句柄。SOL_SOCKET
:这个参数告诉系统,我要设置的是通用套接字选项。SO_REUSEADDR
:这个就是具体的选项,表示允许地址复用。on
:这个是一个整型变量,我把它设置成 1,表示开启这个选项。sizeof(on)
:这个就是选项值的长度。
我当时觉得,这代码写得简直完美!结果一编译运行,直接给我报错。我当时就懵,这是咋回事儿?
然后,我就开始漫长的调试过程。我各种查资料、尝试不同的参数组合,甚至还去请教一些前辈。我才发现,原来是我对 setsockopt
的理解还不够深入。这玩意儿虽然看起来简单,但实际上涉及到很多底层的网络知识。比如说,不同的选项对应着不同的 level,有些选项是通用的,有些选项则是针对特定协议的;再比如说,选项值的类型也各不相同,有些是整型,有些是布尔型,还有些是结构体……
经过一番折腾,我终于把 setsockopt
搞明白。原来设置不同的选项,level
参数也需要跟着变。比如我要设置 TCP 相关的选项,就得用 IPPROTO_TCP
。而且不同的选项,传进去的值也完全不一样,有的要传 int
,有的得传结构体。当时可把我给折腾坏,试好多次才搞清楚这些东西都是怎么配套使用的。
总结一下我的经验:
- 搞清楚选项的含义: 每个选项都有其特定的作用,一定要弄明白它是干啥的,才能正确地使用它。
- 选择正确的 level: 不同的选项对应着不同的 level,要根据选项的类型来选择正确的 level。
- 使用正确的选项值类型: 不同的选项需要不同类型的选项值,要根据选项的要求来设置选项值。
现在想想,也不难,就是当时啥也不懂,也没人教我,只能自己在那儿瞎琢磨。不过也正是因为有这回经历,我对套接字编程的理解才更深一层。我已经能熟练地使用 setsockopt
来控制套接字的各种行为,感觉自己又变强一点点!哈哈!
经过这回实践,以后不管是对什么套接字设置选项值,只要使用 setsockopt 函数,配置对应的 level、optname 等,就能对指定的网络套接字设置选项值。真是个不错的小技巧!