Linux和Solaris中的setsockopt用法[Solaris中的无效参数]

时间:2018-02-07 17:48:58

标签: c linux sockets solaris

我正在尝试在我的ftp程序中在Linux和Solaris上使用setsockopt()

Linux使用long作为optvalue作为参数,但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中报告“无效参数”。

1 个答案:

答案 0 :(得分:3)

问题中出现了两个问题:

  •   

    Linux使用long作为参数的optvalue,但Solaris使用char   代替。

TL; DR:你应该到处使用int

在Solaris中,setsockopt()的定义可能略有不同,具体取决于Solaris的版本和程序链接的库,例如Solaris 10 setsockopt (3SOCKET),{{3}和Solaris 11' setsockopt (3XNET)setsockopt (3SOCKET)setsockopt (3XNET)与Solaris'}共享相同的内容。 (3SOCKET)联机帮助页:

  

大多数套接字级选项都使用 int 参数进行optval。对于   setsockopt(),参数应该非零以启用布尔值   选项,如果要禁用该选项,则为零。

(3XNET)只是没有说明bolean选项的类型。然而,另一个UNIX(AIX)在Linux' manpage上也有旧的* BSD和UNIX98 / XOPEN版本,它们对于布尔值来说是int。关于使用char的混淆来自(* BSD样式)示例,使用指针转换为(char *)而不是(const void *),因为原型使用char *来表示* BSD / 3XNET。这并不意味着参数为char。至于long,除了不在定义之外,还有single page那些错误的架构。请注意,Windows与* NIX不同。

  • size_t len = sizeof(char);
    

除了sizeof val应该首选,并且可以直接在setsockopt()中使用,而不需要首先使用lenlen是在Solaris(3XNET)上定义为int,在Solaris(3SOCKET)和Linux上定义为socklen_t,而在任何地方定义为size_tint socklen_t为什么size_t通过size_t短暂(和错误)通过size_t。当int未定义为protected void requestBoth() { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CAMERA}, MULT_KEY); } protected void requestLoc() { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCPERMISSION_KEY); } protected void requestCam() { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, CAMPERMISSION_KEY); } public void request() { if ((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) && (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)) { requestUpdates(); } else if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { requestCam(); } else if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { requestLoc(); } else { requestBoth(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (Build.VERSION.SDK_INT >= 23) { request(); } } 时,使用其他类型(例如Linux上的re.sub)可能会破坏某些体系结构(请参阅前面的2个链接)。