Como usar a API do soquete C no C ++ no z / OS

158

Estou tendo problemas recebendo o soquetes C API para funcionar corretamente no C++on z/OS.

Embora eu esteja incluindo sys/socket.h, ainda recebo erros de tempo de compilação informando que isso AF_INETnão está definido .

Estou perdendo algo óbvio, ou isso está relacionado ao fato de estar ligado z/OStorna meus problemas muito mais complicados?


Atualização : Após uma investigação mais aprofundada, descobri que há um #ifdefque estou atingindo. Aparentemente, z/OSnão é feliz, a menos que eu defina com qual "tipo" de soquetes estou usando:

#define _OE_SOCKETS

Agora, pessoalmente, eu não tenho ideia do que _OE_SOCKETSé isso, de modo que, se houver algum z/OSprogramador de soquetes (todos vocês três), talvez você possa me dar um resumo de como tudo isso funciona?


Test App

#include <sys/socket.h>

int main()
{
    return AF_INET;
}

Saída de compilação / link:

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.

Uma verificação de sys / sockets.h inclui a definição de que preciso e, tanto quanto posso dizer, ela não está sendo bloqueada por nenhuma #ifdefinstrução.

No entanto, notei que ele contém o seguinte:

#ifdef __cplusplus
  extern "C" {
#endif

que encapsula basicamente o arquivo inteiro? Não tenho certeza se isso importa.

Jax
fonte

Respostas:

86

Mantenha uma cópia dos manuais IBM à mão:

As publicações da IBM geralmente são muito boas, mas você precisa se acostumar com seu formato, além de saber onde procurar uma resposta. Você encontrará muitas vezes que um recurso que deseja usar é protegido por uma "macro de teste de recurso"

Você deve solicitar ao seu programador de sistema amigável que instale a Referência da biblioteca de tempo de execução XL C / C ++: páginas de manual no seu sistema. Em seguida, você pode fazer coisas como "man connect" para acessar a página de manual da API socket connect (). Quando faço isso, é o que vejo:

FORMATO

X / Aberto

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

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

Berkeley Sockets

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

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

Não tive problemas para usar a API de soquetes BSD em C ++, no GNU / Linux. Aqui está o programa de amostra que eu usei:

#include <sys/socket.h>

int
main()
{
    return AF_INET;
}

Portanto, minha opinião é que o z / OS provavelmente é o fator complicador aqui, no entanto, porque nunca usei o z / OS antes, muito menos programado nele, não posso dizer isso definitivamente. :-P

Chris Jester-Young
fonte
32

Consulte a seção Usando soquetes dos Serviços do Sistema z / OS UNIX no Guia de Programação do z / OS XL C / C ++. Certifique-se de incluir os arquivos de cabeçalho necessários e usar os #defines apropriados.

O link para o documento mudou ao longo dos anos, mas você poderá acessá-lo com bastante facilidade, localizando a localização atual da seção Suporte e downloads no ibm.com e pesquisando a documentação por título.

Robert Groves
fonte
26

O _OE_SOCKETS parece ser simplesmente para ativar / desativar a definição de símbolos relacionados ao soquete. Em algumas bibliotecas, não é incomum ter várias macros para fazer isso, para garantir que você não esteja compilando / vinculando partes desnecessárias. A macro não é padrão em outras implementações de soquetes, parece ser algo específico para o z / OS.

Dê uma olhada nesta página:
Compilando e vinculando um z / VM C Sockets Program

Fabio Ceconello
fonte
2
O z / OS tem tanto em comum com o z / VM quanto o Windows com o Linux, então estou um pouco confuso por que você postou esse link.
22420
Observe que a macro _OE_SOCKETS aparece nos dois e parece ter o mesmo objetivo. O que não é surpreendente, já que provavelmente a IBM usou a mesma base de código para suporte de soquete nos dois produtos. Não pretendia dizer que a documentação do z / VM se aplica ao z / OS, é apenas o caso mais semelhante que encontrei.
Fabio Ceconello 06/06/2009
1
Eu acho que é apenas uma coincidência. O z / VM não usa o produto z / OS Language Environment, que fornece os arquivos de cabeçalho relevantes usados ​​para fazer chamadas de soquete.
Anthony Giorgio
25

Então tente

#define _OE_SOCKETS

antes de incluir sys / socket.h

fizzer
fonte
19

Você pode dar uma olhada em cpp-sockets , um wrapper C ++ para as chamadas do sistema de soquetes. Funciona com muitos sistemas operacionais (Win32, POSIX, Linux, * BSD). Não acho que funcione com o z / OS, mas você pode dar uma olhada nos arquivos de inclusão que ele usa e terá muitos exemplos de código testado que funcionam bem em outros sistemas operacionais.

Federico
fonte
18

@Jax: A extern "C"coisa importa, muito, muito. Se um arquivo de cabeçalho não tiver um, então (a menos que seja um arquivo de cabeçalho somente em C ++), você deverá anexá #include-lo a ele:

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

Basicamente, sempre que um programa C ++ deseja se vincular a instalações baseadas em C, isso extern "C"é vital. Em termos práticos, isso significa que os nomes usados ​​nas referências externas não serão mutilados, como nomes C ++ normais. Referência.

Chris Jester-Young
fonte
14

AVISO LEGAL: Eu não sou um programador de C ++, no entanto, eu sei C muito bem. Eu adaptei essas chamadas de algum código C que eu tenho.

Também o markdown coloca esses _ estranhos como meus sublinhados.

Você deve conseguir escrever uma classe de abstração em torno dos soquetes C com algo como isto:

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

Em seguida, tenha métodos para abrir, fechar e enviar pacotes pelo soquete.

Por exemplo, a chamada aberta pode ser algo como isto:

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
fonte
Isso não tem nada a ver com a pergunta original.
Anthony Giorgio
13

Use o seguinte sinalizador c89:

 -D_OE_SOCKETS

Exemplo:

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

Para obter mais informações, procure as Opções do c89 no Guia do Usuário do z / OS XLC / C ++.

Hope T. Ajuda
fonte