Cómo utilizar la API de socket C en C++ en z/OS
Pregunta
Tengo problemas para que la API de sockets C funcione correctamente en C++ en z/OS
.
Aunque estoy incluyendo sys/socket.h
, todavía recibo errores en tiempo de compilación que me dicen que AF_INET
no está definido.
¿Me estoy perdiendo algo obvio o está relacionado con el hecho de que estar en z/OS
¿Hace mis problemas mucho más complicados?
Actualizar:Tras una mayor investigación, descubrí que hay una #ifdef
que estoy pegando.Aparentemente z/OS
no está contento a menos que defina con qué "tipo" de sockets estoy usando:
#define _OE_SOCKETS
Ahora bien, personalmente no tengo idea de qué es esto. _OE_SOCKETS
es en realidad para, así que si hay alguno z/OS
Hay programadores de sockets (ustedes 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;
}
Salida de compilación/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 verificación de sys/sockets.h incluye la definición que necesito y, hasta donde puedo decir, ninguna declaración #ifdef la bloquea.
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.
Solución
Tenga a mano una copia de los manuales de IBM:
- Guía de programación de z/OS V1R11.0 XL C/C++
- Referencia de la biblioteca en tiempo de ejecución de z/OS V1R11.0 XL C/C++
Las publicaciones de IBM en general son muy buenas, pero es necesario acostumbrarse a su formato, además de saber dónde buscar una respuesta.Con bastante frecuencia encontrará que una función que desea utilizar está protegida por una "macro de prueba de funciones".
Debe pedirle a su amigable programador de sistemas que instale el Referencia de la biblioteca en 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 de manual de la API socket connect().Cuando hago eso, esto es lo que veo:
FORMATO
X/Abrir
#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);
Otros consejos
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;
}
Así que mi opinión sobre esto es que z/OS es probablemente el factor que complica la situación, sin embargo, como nunca he usado z/OS antes, y mucho menos he programado en él, no puedo decir esto definitivamente.:-PAG
Ver el Utilización de sockets de servicios del sistema z/OS UNIX de la Guía de programación de z/OS XL C/C++.Asegúrese de incluir los archivos de encabezado necesarios y de utilizar los #defines adecuados.
El enlace al documento ha cambiado a lo largo de los años, pero debería poder acceder a él con bastante facilidad si encuentra la ubicación actual del Sección de soporte y descargas en ibm.com y buscar la documentación por título.
Así que intenta
#define _OE_SOCKETS
antes de incluir sys/socket.h
_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 asegurar que no estés compilando/vinculando partes que no sean necesarias.La macro no es estándar en otras implementaciones de sockets, parece ser algo específico de z/OS.
Échale un vistazo a esta página:
Compilación y vinculación de un programa de sockets z/VM C
Quizás quieras echar un vistazo a enchufes-cpp, 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 puedes echar un vistazo a los archivos de inclusión que utiliza y tendrás muchos ejemplos de código probado que funciona bien en otros sistemas operativos.
@Jax:El extern "C"
La cosa importa, muchísimo.Si un archivo de encabezado no tiene uno, entonces (a menos que sea un archivo de encabezado solo de C++), deberá adjuntar su #include
con eso:
extern "C" {
#include <sys/socket.h>
// include other similarly non-compliant header files
}
Básicamente, en cualquier momento en el que un programa C++ quiera vincularse a instalaciones basadas en C, el extern "C"
Es vital.En términos prácticos, significa que los nombres utilizados en las referencias externas no serán alterados, como lo harían los nombres normales de C++. Referencia.
DESCARGO DE RESPONSABILIDAD:No soy programador de C++, pero conozco muy bien C.Adapté estas llamadas de algún código C que tengo.
También Markdown puso estos _ extraños como guiones bajos.
Deberías 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;
}
La respuesta es utilizar el indicador c89 que sigue:
-D_OE_SOCKETS
A continuación se muestra el ejemplo;
bash-2.03$ c89 -D_OE_SOCKETS [filename].c
Para obtener más información, busque Opciones de C89 en la Guía del usuario de z/OS XLC/C++.