Как использовать API сокета C в C++ на z/OS

У меня возникают проблемы с правильной работой API сокетов C в C++ на z/OS.

Хотя я включаю 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

который инкапсулирует в основном весь файл? Не уверен, имеет ли это значение.

Ответов (9)

Решение

Держите под рукой копии руководств IBM:

Публикации IBM в целом очень хороши, но вам нужно привыкнуть к их формату, а также знать, где искать ответ. Довольно часто вы обнаруживаете, что функция, которую вы хотите использовать, защищена «макросом проверки функции».

Вам следует попросить своего дружелюбного системного программиста установить в вашей системе Справочник по библиотеке времени выполнения XL C/C++: Man Pages . Затем вы можете сделать что-то вроде "man connect", чтобы открыть страницу руководства по API-интерфейсу socket (). Когда я это делаю, я вижу следующее:

ФОРМАТ

X / Открыть

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

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

Розетки Беркли

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

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

@Jax: Это extern "C" очень важно. Если в файле заголовка его нет, тогда (если это не файл заголовка, предназначенный только для C++), вам придется приложить к нему свой #include :

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

По сути, в любое время, когда программа на C++ хочет подключиться к средствам на основе C, extern "C" очень важно. На практике это означает, что имена, используемые во внешних ссылках, не будут искажены, как обычные имена C++. Ссылка.

У меня не было проблем с использованием API сокетов BSD на C++ в GNU / Linux. Вот пример программы, которую я использовал:

#include <sys/socket.h>

int
main()
{
    return AF_INET;
}

Итак, я считаю, что z/OS, вероятно, является здесь усложняющим фактором, однако, поскольку я никогда раньше не использовал z/OS, не говоря уже о программировании в ней, я не могу сказать об этом окончательно. :-П

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я не программист на C++, но я очень хорошо знаю C. Я адаптировал эти вызовы из имеющегося у меня кода C.

Также уценка поместила эти странные _ в качестве подчеркивания.

Вы должны просто написать класс абстракции вокруг сокетов C примерно так:

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;
}

Возможно, вы захотите взглянуть на cpp-sockets , оболочку C++ для системных вызовов сокетов. Он работает со многими операционными системами (Win32, POSIX, Linux, * BSD). Я не думаю, что он будет работать с z/OS, но вы можете взглянуть на включаемые файлы, которые он использует, и у вас будет много примеров протестированного кода, который хорошо работает в других ОС.

Так что постарайтесь

#define _OE_SOCKETS

перед включением sys / socket.h

_OE_SOCKETS, похоже, просто для включения / отключения определения символов, связанных с сокетами. В некоторых библиотеках нередко есть набор макросов для этого, чтобы гарантировать, что вы не компилируете / компилируете ненужные части. Макрос не является стандартным для других реализаций сокетов, кажется, что он специфичен для z/OS.

Взгляните на эту страницу:
Компиляция и компоновка программы сокетов z / VM C

См. Раздел Использование сокетов системных служб z/OS UNIX в Руководстве по программированию z/OS XL C/C++. Убедитесь, что вы включаете необходимые файлы заголовков и используете соответствующие #defines.

Ссылка на документ менялась с годами, но вы сможете легко добраться до него, найдя текущее местоположение раздела « Поддержка и загрузки» на ibm.com и выполнив поиск документации по заголовку.

Используйте следующий флаг c89:

 -D_OE_SOCKETS

Пример:

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

Дополнительные сведения см. В разделе «Параметры c89» в Руководстве пользователя z/OS XLC/C++.