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.

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

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


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.


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


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


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.


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.


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

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 ++.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.