Linux 和 Solaris 中的 setsockopt 用法 [Solaris 中的参数无效]
setsockopt usage in Linux and Solaris [Invalid argument in Solaris]
我正在尝试在我的 ftp 程序中同时在 Linux 和 Solaris 上使用 setsockopt()
。
Linux 对 optvalue
使用 long
作为参数,但 Solaris 使用 char
作为参数。
#ifdef sun
char val;
#else
long val;
#endif
#ifdef sun
val = 1;
size_t len = sizeof(char);
if(setsockopt(s_socket_fd, SOL_SOCKET, SO_REUSEADDR, &val, len) == -1) {
perror("Fail");
exit(1);
}
#else
val = 1;
size_t len = sizeof(long);
if(setsockopt(s_socket_fd, SOL_SOCKET, SO_REUSEADDR, &val, len) == -1) {
perror("Fail");
exit(1);
}
#endif
该程序在 Linux 中运行良好,但在创建套接字时在 Solaris 中报告 "Invalid argument"。
题目中出现了2个问题:
Linux uses a long
for optvalue as a parameter, but Solaris uses a char
instead.
TL;DR:你应该在所有地方使用 int
。
在 Solaris 中,setsockopt()
的定义可能略有不同,具体取决于 Solaris 的版本和程序所链接的库,例如 Solaris 10 的 setsockopt (3SOCKET), setsockopt (3XNET) and Solaris 11's setsockopt (3SOCKET), setsockopt (3XNET). Linux' manpage 与 Solaris 共享相同的内容(3SOCKET) 联机帮助页:
Most socket-level options utilize an int argument for optval. For
setsockopt(), the argument should be nonzero to enable a boolean
option, or zero if the option is to be disabled.
(3XNET) 只是没有说明布尔选项的类型。 Yet-an-other-UNIX (AIX) 也有旧的 *BSD 和 UNIX98/XOPEN 版本,在 single page, where it's an int
for booleans. The confusion about using char
comes from (*BSD-style) examples using a pointer cast to (char *)
instead of (const void *)
, because the prototype is using char *
for *BSD/3XNET. That doesn't mean the parameter is char
. As for long
, beside not being in the definition, on architectures where long
is not int
上是错误的。请注意 Windows 与 *NIX 不同。
size_t len = sizeof(char);
除了 sizeof val
应该是首选,并且可以直接在 setsockopt()
中使用,甚至不需要首先在这里使用 len
,len
在 Solaris (3XNET) 上定义为 int
,在 Solaris (3SOCKET) 上定义为 socklen_t
,在任何地方都定义为 Linux,而不是 size_t
。 Link to a possible explanation 关于为什么 int
变成了 socklen_t
,通过 size_t
的简短(错误)段落。当 size_t
未定义为 int
时,使用其他类型(例如 Linux 上的 size_t
)可能会在某些体系结构上中断(请参阅前面的 2 个链接)。
我正在尝试在我的 ftp 程序中同时在 Linux 和 Solaris 上使用 setsockopt()
。
Linux 对 optvalue
使用 long
作为参数,但 Solaris 使用 char
作为参数。
#ifdef sun
char val;
#else
long val;
#endif
#ifdef sun
val = 1;
size_t len = sizeof(char);
if(setsockopt(s_socket_fd, SOL_SOCKET, SO_REUSEADDR, &val, len) == -1) {
perror("Fail");
exit(1);
}
#else
val = 1;
size_t len = sizeof(long);
if(setsockopt(s_socket_fd, SOL_SOCKET, SO_REUSEADDR, &val, len) == -1) {
perror("Fail");
exit(1);
}
#endif
该程序在 Linux 中运行良好,但在创建套接字时在 Solaris 中报告 "Invalid argument"。
题目中出现了2个问题:
Linux uses a
long
for optvalue as a parameter, but Solaris uses achar
instead.
TL;DR:你应该在所有地方使用 int
。
在 Solaris 中,setsockopt()
的定义可能略有不同,具体取决于 Solaris 的版本和程序所链接的库,例如 Solaris 10 的 setsockopt (3SOCKET), setsockopt (3XNET) and Solaris 11's setsockopt (3SOCKET), setsockopt (3XNET). Linux' manpage 与 Solaris 共享相同的内容(3SOCKET) 联机帮助页:
Most socket-level options utilize an int argument for optval. For setsockopt(), the argument should be nonzero to enable a boolean option, or zero if the option is to be disabled.
(3XNET) 只是没有说明布尔选项的类型。 Yet-an-other-UNIX (AIX) 也有旧的 *BSD 和 UNIX98/XOPEN 版本,在 single page, where it's an int
for booleans. The confusion about using char
comes from (*BSD-style) examples using a pointer cast to (char *)
instead of (const void *)
, because the prototype is using char *
for *BSD/3XNET. That doesn't mean the parameter is char
. As for long
, beside not being in the definition, on architectures where long
is not int
上是错误的。请注意 Windows 与 *NIX 不同。
size_t len = sizeof(char);
除了 sizeof val
应该是首选,并且可以直接在 setsockopt()
中使用,甚至不需要首先在这里使用 len
,len
在 Solaris (3XNET) 上定义为 int
,在 Solaris (3SOCKET) 上定义为 socklen_t
,在任何地方都定义为 Linux,而不是 size_t
。 Link to a possible explanation 关于为什么 int
变成了 socklen_t
,通过 size_t
的简短(错误)段落。当 size_t
未定义为 int
时,使用其他类型(例如 Linux 上的 size_t
)可能会在某些体系结构上中断(请参阅前面的 2 个链接)。