Come utilizzare l'API socket C in C++ su z/OS
Domanda
Ho problemi a far funzionare correttamente l'API dei socket C in C++ z/OS
.
Anche se sto includendo sys/socket.h
, ricevo ancora errori in fase di compilazione che me lo dicono AF_INET
non è definito.
Mi sto perdendo qualcosa di ovvio, o questo è legato al fatto che essere attivo z/OS
rende i miei problemi molto più complicati?
Aggiornamento:Dopo ulteriori indagini, ho scoperto che esiste un file #ifdef
che sto colpendo.Apparentemente z/OS
non è felice a meno che non definisca quale "tipo" di socket sto utilizzando con:
#define _OE_SOCKETS
Ora, personalmente non ho idea di cosa questo _OE_SOCKETS
è in realtà per, quindi se presente z/OS
ci sono programmatori di socket (tutti e 3), forse potreste darmi un riassunto di come funziona tutto questo?
Prova l'app
#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 è bloccato da alcuna istruzione #ifdef.
Ho notato però che contiene quanto segue:
#ifdef __cplusplus
extern "C" {
#endif
che incapsula sostanzialmente l'intero file.Non sono sicuro che sia importante.
Soluzione
Tieni a portata di mano una copia dei manuali IBM:
- Guida alla programmazione z/OS V1R11.0 XL C/C++
- Riferimento alla libreria runtime z/OS V1R11.0 XL C/C++
Le pubblicazioni IBM sono generalmente molto buone, ma è necessario abituarsi al loro formato, oltre a sapere dove cercare una risposta.Scoprirai molto spesso che una funzionalità che desideri utilizzare è protetta da una "macro di test delle funzionalità"
Dovresti chiedere al tuo amichevole programmatore di sistema di installare il file Riferimento alla libreria runtime XL C/C++:Pagine uomo sul tuo sistema.Quindi puoi fare cose come "man connect" per aprire la pagina man per l'API socket connect().Quando lo faccio, questo è quello che vedo:
FORMATO
X/Apri
#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);
Altri suggerimenti
Non ho avuto problemi con l'utilizzo dell'API dei 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 a riguardo è che z/OS è probabilmente il fattore complicante qui, tuttavia, poiché non ho mai usato z/OS prima, tanto meno programmato al suo interno, non posso dirlo in modo definitivo.:-P
Vedi il Utilizzo dei socket dei servizi di sistema z/OS UNIX sezione nella Guida alla programmazione z/OS XL C/C++.Assicurati di includere i file di intestazione necessari e di utilizzare le #defines appropriate.
Il collegamento al documento è cambiato nel corso degli anni, ma dovresti riuscire ad accedervi abbastanza facilmente trovando la posizione attuale del documento Sezione Supporto e download SU ibm.com e cercare la documentazione per titolo.
Allora prova
#define _OE_SOCKETS
prima di includere sys/socket.h
Sembra che _OE_SOCKETS serva semplicemente ad abilitare/disabilitare la definizione dei simboli relativi al socket.Non è raro in alcune librerie avere un sacco di macro per farlo, per assicurarsi che non si stiano compilando/collegando parti non necessarie.La macro non è standard in altre implementazioni socket, sembra essere qualcosa di specifico per z/OS.
Dai un'occhiata a questa pagina:
Compilazione e collegamento di un programma z/VM C Sockets
Potresti voler dare un'occhiata a socket cpp, un wrapper C++ per le chiamate di sistema socket.Funziona con molti sistemi operativi (Win32, POSIX, Linux, *BSD).Non penso che funzionerà con z/OS ma puoi dare un'occhiata ai file di inclusione che utilizza e avrai molti esempi di codice testato che funziona bene su altri sistemi operativi.
@Jax:IL extern "C"
la cosa conta, moltissimo.Se un file di intestazione non ne ha uno, allora (a meno che non sia un file di intestazione solo C++), dovresti racchiudere il tuo #include
con 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, il file extern "C"
è vitale.In termini pratici, significa che i nomi utilizzati nei riferimenti esterni non verranno alterati, come farebbero i normali nomi C++. Riferimento.
DISCLAIMER:Non sono un programmatore C++, tuttavia conosco molto bene il C.Ho adattato queste chiamate da un codice C che ho.
Anche il ribasso ha messo questi strani _ come sottolinea il mio.
Dovresti semplicemente 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 disponi di metodi per aprire, chiudere e inviare pacchetti lungo il socket.
Ad esempio, la chiamata aperta potrebbe assomigliare 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;
}
La risposta è utilizzare il flag c89 che segue:
-D_OE_SOCKETS
Segue l'esempio;
bash-2.03$ c89 -D_OE_SOCKETS [filename].c
Per ulteriori informazioni cercare Opzioni C89 nella Guida per l'utente di z/OS XLC/C++.