Cómo utilizar la API de socket C en C ++ en z / OS

158

Estoy teniendo problemas para conseguir la API de sockets C para que funcione correctamente en C++el z/OS.

Aunque lo estoy incluyendo sys/socket.h, todavía recibo errores de tiempo de compilación que me dicen que AF_INETno está definido .

¿Me estoy perdiendo algo obvio, o está relacionado con el hecho de que estar en él z/OScomplica mis problemas?


Actualización : Tras una investigación más profunda, descubrí que hay una #ifdefque estoy golpeando. Aparentemente z/OSno es feliz a menos que defina con qué "tipo" de sockets estoy usando:

#define _OE_SOCKETS

Ahora, personalmente no tengo idea de para qué _OE_SOCKETSes esto , así que si hay algún z/OSprogramador de sockets (los 3), ¿tal vez podrían darme un resumen de cómo funciona todo esto?


Aplicación de prueba

#include <sys/socket.h>

int main()
{
    return AF_INET;
}

Compilar / Salida de enlace:

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.

Una comprobación de sys / sockets.h incluye la definición que necesito y, por lo que puedo decir, no está bloqueada por ninguna #ifdefdeclaración.

Sin embargo, he notado que contiene lo siguiente:

#ifdef __cplusplus
  extern "C" {
#endif

que encapsula básicamente todo el archivo? No estoy seguro si importa.

Jax
fuente

Respuestas:

86

Mantenga una copia de los manuales de IBM a mano:

Las publicaciones de IBM son generalmente muy buenas, pero debe acostumbrarse a su formato, así como saber dónde buscar una respuesta. Encontrará con bastante frecuencia que una característica que desea utilizar está protegida por una "macro de prueba de características"

Debe pedirle a su amigable programador del sistema que instale la Referencia de la Biblioteca de tiempo de ejecución XL C / C ++: Páginas Man en su sistema. Luego puede hacer cosas como "man connect" para abrir la página man para la API de socket connect (). Cuando hago eso, esto es lo que veo:

FORMATO

X / abierto

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

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

Enchufes Berkeley

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

int connect(int socket, struct sockaddr *address, int address_len);
Anthony Giorgio
fuente
38

No he tenido problemas para usar la API de sockets BSD en C ++, en GNU / Linux. Aquí está el programa de muestra que utilicé:

#include <sys/socket.h>

int
main()
{
    return AF_INET;
}

Entonces, mi opinión sobre esto es que z / OS es probablemente el factor de complicación aquí, sin embargo, porque nunca he usado z / OS antes, y mucho menos programado en él, no puedo decirlo definitivamente. :-PAGS

Chris Jester-Young
fuente
32

Consulte la sección Uso de zócalos de servicios del sistema z / OS UNIX en la Guía de programación de z / OS XL C / C ++. Asegúrese de incluir los archivos de encabezado necesarios y usar los #defines apropiados.

El enlace al documento ha cambiado a lo largo de los años, pero debería poder acceder a él fácilmente encontrando la ubicación actual de la sección de Soporte y descargas en ibm.com y buscando en la documentación por título.

Robert Groves
fuente
26

El _OE_SOCKETS parece ser simplemente para habilitar / deshabilitar la definición de símbolos relacionados con sockets. No es raro en algunas bibliotecas tener un montón de macros para hacer eso, para asegurarse de que no está compilando / vinculando partes que no son necesarias. La macro no es estándar en otras implementaciones de sockets, parece ser algo específico de z / OS.

Eche un vistazo a esta página:
Compilar y vincular el programa z / VM C Sockets

Fabio Ceconello
fuente
2
z / OS tiene tanto en común con z / VM como Windows con Linux, por lo que estoy un poco desconcertado por qué publicó ese enlace.
paxdiablo
Observe que la macro _OE_SOCKETS aparece en ambos y parece tener el mismo propósito. Lo cual no es sorprendente, ya que probablemente IBM utilizó la misma base de código para el soporte de socket en ambos productos. No tenía la intención de decir que la documentación de z / VM se aplica a z / OS, es solo el caso más similar que encontré.
Fabio Ceconello
1
Creo que es solo una coincidencia. z / VM no utiliza el producto z / OS Language Environment, que proporciona los archivos de encabezado relevantes utilizados para realizar llamadas de socket.
Anthony Giorgio
25

Así que intenta

#define _OE_SOCKETS

antes de incluir sys / socket.h

fizzer
fuente
19

Es posible que desee echar un vistazo a cpp-sockets , un contenedor de C ++ para las llamadas al sistema de sockets. Funciona con muchos sistemas operativos (Win32, POSIX, Linux, * BSD). No creo que funcione con z / OS, pero puede echar un vistazo a los archivos de inclusión que usa y tendrá muchos ejemplos de código probado que funciona bien en otros sistemas operativos.

Federico
fuente
18

@Jax: La extern "C"cosa importa, mucho, mucho. Si un archivo de encabezado no tiene uno, entonces (a menos que sea un archivo de encabezado solo C ++), deberá adjuntarlo #includecon él:

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

Básicamente, en cualquier momento en que un programa C ++ quiera vincularse a instalaciones basadas en C, extern "C"es vital. En términos prácticos, significa que los nombres usados ​​en referencias externas no serán mutilados, como lo harían los nombres normales de C ++. Referencia.

Chris Jester-Young
fuente
14

DESCARGO DE RESPONSABILIDAD: No soy un programador de C ++, sin embargo, conozco C muy bien. Adapté estas llamadas de algún código C que tengo.

También Markdown puso estos _ extraños como mis guiones bajos.

Debería poder escribir una clase de abstracción alrededor de los sockets C con algo como esto:

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

Luego tenga métodos para abrir, cerrar y enviar paquetes por el socket.

Por ejemplo, la convocatoria abierta podría verse así:

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;
}
David Bryson
fuente
Esto no tiene nada que ver con la pregunta original.
Anthony Giorgio
13

Use la siguiente bandera c89:

 -D_OE_SOCKETS

Ejemplo:

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

Para obtener más información, busque las Opciones de c89 en la Guía del usuario de z / OS XLC / C ++.

Hope T. ayuda
fuente