如果套接字被设置为侦听,如何在MacOS上获得选项



我使用一个简单的谷歌测试如何获取套接字是否设置为侦听。套接字级别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现在对其协议感到满意,但它将trueso_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,它将失败。

相关内容

最新更新