Come utilizzare l'API socket C in C ++ su z / OS


158

Sto avendo problemi di ottenere l'API socket C per funzionare correttamente in C++su z/OS.

Anche se sto includendo sys/socket.h, ricevo ancora errori di compilazione che mi dicono che AF_INETnon è definito .

Mi sto perdendo qualcosa di ovvio, o è collegato al fatto che essere su z/OSrende i miei problemi molto più complicati?


Aggiornamento : su ulteriori indagini, ho scoperto che c'è un #ifdefche sto colpendo. Apparentemente z/OSnon è felice a meno che non definisca con quale "tipo" di socket sto usando:

#define _OE_SOCKETS

Ora, personalmente non ho idea di cosa _OE_SOCKETSsia effettivamente fatto, quindi se qualche z/OSprogrammatore di socket è là fuori (tutti e tre), forse potresti darmi una carrellata di come funziona tutto questo?


App di prova

#include <sys/socket.h>

int main()
{
    return AF_INET;
}

Compila / collega output:

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.

Un controllo di sys / sockets.h include la definizione di cui ho bisogno e, per quanto ne so, non viene bloccato da alcuna #ifdefistruzione.

Ho comunque notato che contiene quanto segue:

#ifdef __cplusplus
  extern "C" {
#endif

quale incapsula sostanzialmente l'intero file? Non sono sicuro che sia importante.

Risposte:


86

Tenere a portata di mano una copia dei manuali IBM:

Le pubblicazioni IBM sono generalmente molto buone, ma è necessario abituarsi al loro formato, oltre a sapere dove cercare una risposta. Scoprirai abbastanza spesso che una funzione che desideri utilizzare è protetta da una "macro di test di funzionalità"

Dovresti chiedere al tuo programmatore di sistema amichevole di installare XL C / C ++ Run-Time Reference Library: Man Pages sul tuo sistema. Quindi puoi fare cose come "man connect" per estrarre la pagina man per l'API socket connect (). Quando lo faccio, questo è quello che vedo:

FORMATO

X / Open

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

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

Prese Berkeley

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

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

38

Non ho avuto problemi a usare l'API socket BSD in C ++, in GNU / Linux. Ecco il programma di esempio che ho usato:

#include <sys/socket.h>

int
main()
{
    return AF_INET;
}

Quindi la mia opinione su questo è che z / OS è probabilmente il fattore complicante qui, tuttavia, poiché non ho mai usato z / OS prima, tanto meno programmato in esso, non posso dirlo definitivamente. :-P


32

Vedere la sezione Uso dei socket dei servizi di sistema UNIX z / OS nella Guida alla programmazione c / C ++ z / OS XL. Assicurati di includere i file di intestazione necessari e di utilizzare le #define appropriate.

Il link al documento è cambiato nel corso degli anni, ma dovresti riuscire a raggiungerlo abbastanza facilmente trovando la posizione corrente della sezione Supporto e download su ibm.com e cercando la documentazione per titolo.


26

_OE_SOCKETS sembra essere semplicemente per abilitare / disabilitare la definizione di simboli relativi al socket. In alcune librerie non è raro avere un sacco di macro per farlo, per assicurare che non si stiano compilando / collegando parti non necessarie. La macro non è standard in altre implementazioni di socket, sembra essere qualcosa di specifico per z / OS.

Dai un'occhiata a questa pagina:
compilazione e collegamento del programma socket Z / VM C


2
z / OS ha tanto in comune con z / VM quanto Windows fa con Linux, quindi sono un po 'confuso dal motivo per cui hai pubblicato quel link.
paxdiablo,

Si noti che la macro _OE_SOCKETS appare in entrambi e sembra avere lo stesso scopo. Ciò non sorprende, poiché probabilmente IBM ha utilizzato la stessa base di codice per il supporto socket in entrambi i prodotti. Non intendevo dire che la documentazione di z / VM si applica a z / OS, è solo il caso più simile che ho trovato.
Fabio Ceconello,

1
Penso che sia solo una coincidenza. z / VM non utilizza il prodotto z / OS Language Environment, che fornisce i file di intestazione pertinenti utilizzati per effettuare chiamate socket.
Anthony Giorgio,

25

Allora prova

#define _OE_SOCKETS

prima di includere sys / socket.h


19

Potresti dare un'occhiata a cpp-sockets , un wrapper C ++ per le chiamate di sistema dei socket. Funziona con molti sistemi operativi (Win32, POSIX, Linux, * BSD). Non credo che funzionerà con z / OS, ma puoi dare un'occhiata ai file include che utilizza e avrai molti esempi di codice testato che funziona bene su altri sistemi operativi.


18

@Jax: la extern "C"cosa conta, moltissimo. Se un file di intestazione non ne ha uno, allora (a meno che non sia un C ++ - solo file di intestazione), dovresti racchiuderlo #includecon esso:

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

Fondamentalmente, ogni volta che un programma C ++ vuole collegarsi a strutture basate su C, extern "C"è vitale. In termini pratici, significa che i nomi utilizzati nei riferimenti esterni non verranno alterati, come farebbero i normali nomi C ++. Riferimento.


14

NOTA BENE: non sono un programmatore C ++, tuttavia conosco C molto bene. Ho adattato queste chiamate da un codice C che ho.

Anche il markdown ha messo questi strani _ come miei sottolineature.

Dovresti essere in grado di scrivere una classe di astrazione attorno ai socket C con qualcosa del genere:

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

Quindi disporre di metodi per aprire, chiudere e inviare pacchetti nel socket.

Ad esempio, la chiamata aperta potrebbe essere simile a questa:

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

Questo non ha nulla a che fare con la domanda originale.
Anthony Giorgio,

13

Utilizzare il seguente flag c89:

 -D_OE_SOCKETS

Esempio:

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

Per ulteriori informazioni, consultare Opzioni c89 nella Guida per l'utente di z / OS XLC / C ++.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.