如何在 z/OS 上使用 C++ 中的 C 套接字 API

176

我在z/OS上使用C++时遇到了C sockets API无法正常工作的问题。

尽管我包含了sys/socket.h,但我仍然会在编译时出现错误,告诉我AF_INET未定义。

我是否漏掉了一些明显的东西,或者这与我在z/OS上的情况使我的问题变得更加复杂有关?

我发现有一个#ifdef,我正在使用它。显然,除非我定义我正在使用哪种类型的套接字,否则z/OS不会开心:

#define _OE_SOCKETS

现在,就我个人而言,我并不知道这个_OE_SOCKETS实际上是用来做什么的,所以如果有任何z/OS套接字程序员(你们只有三个),也许你们可以给我介绍一下这是如何工作的?

测试应用:

#include <sys/socket.h>

int main()
{
    return AF_INET;
}

编译/链接输出:

cxx -Wc,xplink -Wl,xplink -o inet_test inet.C

"./inet.C", line 5.16: CCN5274 (S) The name lookup for "AF_INET" did not find a declaration.
CCN0797(I) Compilation failed for file ./inet.C. Object file not created.

检查sys/sockets.h确实包含我需要的定义,据我所知,它没有被任何#ifdef语句阻止。

然而,我注意到它包含以下内容:

#ifdef __cplusplus
  extern "C" {
#endif

哪个封装了整个文件?不确定这是否重要。


Stack Overflow上的第一个C++问题 - Saaransh Garg
9个回答

97

请保持一份IBM手册的副本:

IBM的出版物通常非常好,但您需要熟悉它们的格式,并知道在哪里寻找答案。 您会发现,您经常想使用的功能由“特征测试宏”保护

您应该要求友好的系统程序员在您的系统上安装XL C/C++ 运行时库参考:Man Pages。 然后,您可以执行像“man connect”这样的操作,以打开套接字connect()API的man页。 当我这样做时,我看到的内容如下:

FORMAT

X/Open

#define _XOPEN_SOURCE_EXTENDED 1
#include <sys/socket.h>

int connect(int socket, const struct sockaddr *address, socklen_t address_len);

伯克利套接字(Berkeley Sockets)

#define _OE_SOCKETS
#include <sys/types.h>
#include <sys/socket.h>

int connect(int socket, struct sockaddr *address, int address_len);

46

我在GNU/Linux中使用C++编写的BSD sockets API没有遇到任何问题。下面是我使用的示例程序:

#include <sys/socket.h>

int
main()
{
    return AF_INET;
}

我的理解是z/OS可能是导致这种复杂情况的因素,但是由于我从未使用过z/OS,更没有在其中编程,所以我不能确定。:-P


39
请参阅 z/OS XL C/C++ 编程指南中的“使用 z/OS UNIX 系统服务套接字”部分。确保包含必要的头文件并使用适当的 #define。
多年来,文档链接已更改,但您应该能够通过找到ibm.com支持和下载部分的当前位置,并按标题搜索文档轻松找到它。

32

因此,请尝试。

#define _OE_SOCKETS

在包含sys/socket.h头文件之前


32

_OE_SOCKETS似乎只是用于启用/禁用与套接字相关符号的定义。某些库中常见的有一堆宏来执行此操作,以确保您不会编译/链接不需要的部分。该宏在其他套接字实现中并不标准,似乎是z/OS特定的。

请参阅此页面:
编译和链接z/VM C套接字程序


2
z/OS和z/VM之间的关系就像Windows和Linux之间的关系一样,因此我有点困惑为什么你会发布那个链接。 - paxdiablo
请注意,_OE_SOCKETS 宏在两个产品中都出现了,并且似乎具有相同的目的。这并不奇怪,因为 IBM 可能在两个产品中使用了相同的代码库来支持套接字。我并不打算说 z/VM 文档适用于 z/OS,只是我找到的最相似的情况。 - Fabio Ceconello
1
我认为这只是巧合。z/VM不使用z/OS语言环境产品,该产品提供用于进行套接字调用的相关头文件。 - Anthony Giorgio

25

@Jax:在IT技术中,extern "C"非常重要。如果一个头文件没有它(除非这是一个仅限于C++的头文件),那么你必须将你的#include语句包含进去。

extern "C" {
#include <sys/socket.h>
// include other similarly non-compliant header files
}

基本上,每当一个C++程序想要链接到基于C的设施时,extern "C"就是至关重要的。实际上,这意味着在外部引用中使用的名称将不会像普通的C++名称一样被搞乱。

参考资料。


25

你可能需要看一下cpp-sockets,这是一个用于封装套接字系统调用的C ++包装器。它适用于许多操作系统(Win32、POSIX、Linux、*BSD)。我认为它不适用于z/OS,但你可以查看它使用的包含文件,并且你会有许多在其他操作系统上运行良好的测试代码示例。


20

声明:我不是一个C++程序员,但我非常熟悉C语言。我从一些我已经有的C代码中改编了这些调用。

此外,Markdown把这些奇怪的_当作我的下划线。

你应该可以像这样编写一个抽象类,围绕着C sockets:

class my_sock {
    private int sock;
    private int socket_type;
    private socklen_t sock_len;
    private struct sockaddr_in server_addr;
    public char *server_ip;
    public unsigned short server_port;
};

接着,需要编写打开、关闭以及通过套接字发送数据包的方法。

比如,打开方法可能类似于:

int my_socket_connect()
{
    int return_code = 0;

    if ( this->socket_type != CLIENT_SOCK ) {
        cout << "This is a not a client socket!\n";
        return -1;
    }

    return_code = connect( this->local_sock, (struct sockaddr *) &this->server_addr, sizeof(this->server_addr));

    if( return_code < 0 ) {
        cout << "Connect() failure! %s\n", strerror(errno);
        return return_code;
    }

    return return_code;
}

这与原始问题无关。 - Anthony Giorgio

19

使用以下c89标志:

 -D_OE_SOCKETS

示例:

 bash-2.03$ c89 -D_OE_SOCKETS [filename].c

欲了解更多信息,请查看 z/OS XLC/C++ 用户指南中的 c89 选项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接