我使用一个简单的谷歌测试如何获取套接字是否设置为侦听。套接字级别SO_ACCEPTCONN
上有一个选项,显示套接字有一个listen()调用。
TEST(SocketTestSuite, check_listen) {
int sockfd = socket(AF_INET6, SOCK_STREAM, 0);
ASSERT_NE(sockfd, INVALID_SOCKET);
int so_option = 987654321;
socklen_t optlen{sizeof(so_option)};
int ret = getsockopt(sockfd, SOL_SOCKET, SO_ACCEPTCONN, &so_option, &optlen);
if (ret != 0) {
perror("Error getsockopt");
}
EXPECT_EQ(so_option, 0);
}
在Linux上,我得到了预期的结果:套接字没有设置为侦听。
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from SocketTestSuite
[ RUN ] SocketTestSuite.check_listen
[ OK ] SocketTestSuite.check_listen (0 ms)
[----------] 1 test from SocketTestSuite (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[ PASSED ] 1 test.
但在MacOS上我得到了:
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from SocketTestSuite
[ RUN ] SocketTestSuite.check_listen
Error getsockopt: Protocol not available
/Users/runner/work/client-server-tcp/client-server-tcp/test_client-server-tcp.cpp:165: Failure
Expected equality of these values:
so_option
Which is: 987654321
0
[ FAILED ] SocketTestSuite.check_listen (0 ms)
[----------] 1 test from SocketTestSuite (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] SocketTestSuite.check_listen
为什么它会抱怨"协议不可用">?什么协议?SO_ACCEPTCONN
是一个套接字选项。不管怎样,如果我使用TCP协议编号6与:
int ret = getsockopt(sockfd, 6, SO_ACCEPTCONN, &so_option, &optlen);
我得到这个结果:
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from SocketTestSuite
[ RUN ] SocketTestSuite.check_listen
/Users/runner/work/client-server-tcp/client-server-tcp/test_client-server-tcp.cpp:164: Failure
Expected equality of these values:
so_option
Which is: 1024
0
[ FAILED ] SocketTestSuite.check_listen (0 ms)
[----------] 1 test from SocketTestSuite (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] SocketTestSuite.check_listen
MacOS现在对其协议感到满意,但它将true的so_option = 1024
显示为选项!=0。这是错误的。套接字未设置为侦听。1024是0x400,看起来像是一个位集选项,但我不知道为什么会给出这个选项。
这是怎么回事?为什么MacOS不能像Linux那样正常工作?
参考:
Mac OS X标准socket.h文件
getsockopt()--获取与套接字关联的选项
"协议不可用";是ENOPROTOOPT
的文本错误消息,这是errno
在尝试使用(get|set)sockopt()
选项时报告的消息;在所指示的水平上未知";。
换句话说,这意味着MacOS正在告诉您,它无法识别SOL_SOCKET
级别的SO_ACCEPTCONN
选项。这是有道理的,因为根据苹果公司针对getsockopt()
和setsockopt()
的OSX文档(并经各种在线来源确认),SO_ACCEPTCONN
不是一个受支持的选项。
CCD_ 12的数值为CCD_。通过将级别设置为6
(IPPROTO_TCP
),您将向getsockopt()
询问TCP选项2,即TCP_MAXSEG
(传出TCP数据包的最大段大小)。
因此,你需要相应地调整你的测试:
TEST(SocketTestSuite, check_listen) {
int sockfd = socket(AF_INET6, SOCK_STREAM, 0);
ASSERT_NE(sockfd, INVALID_SOCKET);
int so_option = 0;
socklen_t optlen = sizeof(so_option);
int ret = getsockopt(sockfd, SOL_SOCKET, SO_ACCEPTCONN, &so_option, &optlen);
if (ret < 0) {
if (errno != ENOPROTOOPT)
FAIL() << "Error getsockopt: " << strerror(errno);
else
FAIL() << "Option not supported by getsockopt";
}
else {
EXPECT_EQ(so_option, 0);
}
close(sockfd);
}
AFAIK,没有其他getsockopt()
选项可以取代SO_ACCEPTCONN
。我知道的测试套接字是否在侦听的唯一方法是使用accept()
,如果在未侦听的套接字上调用EINVAL
,它将失败。