Pergunta

Estou tendo problemas para fazer com que a API de soquetes C funcione corretamente em C++ em z/OS.

Embora eu esteja incluindo sys/socket.h, ainda recebo erros de tempo de compilação me dizendo que AF_INET não está definido.

Estou perdendo alguma coisa óbvia ou isso está relacionado ao fato de que estar no z/OS torna meus problemas muito mais complicados?


Atualizar:Após uma investigação mais aprofundada, descobri que existe uma #ifdef que estou batendo.Aparentemente z/OS não está satisfeito a menos que eu defina com qual "tipo" de soquetes estou usando:

#define _OE_SOCKETS

Agora, eu pessoalmente não tenho ideia do que isso _OE_SOCKETS é realmente para, então se houver z/OS programadores de soquetes estão por aí (vocês três), talvez vocês possam me dar um resumo de como tudo isso funciona?


Aplicativo de teste

#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 necessária e, até onde sei, ela não está sendo bloqueada por nenhuma instrução #ifdef.

No entanto, notei que contém o seguinte:

#ifdef __cplusplus
  extern "C" {
#endif

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

Foi útil?

Solução

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

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

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

FORMATAR

X/Aberto

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

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

Soquetes Berkeley

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

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

Outras dicas

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

#include <sys/socket.h>

int
main()
{
    return AF_INET;
}

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

Veja o Usando soquetes z/OS UNIX System Services seção no z/OS XL C/C++ Programming Guide.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 encontrando a localização atual do Seção de suporte e downloads sobre ibm.com e pesquisando a documentação por título.

Então tente

#define _OE_SOCKETS

antes de incluir sys/socket.h

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

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

Você pode querer dar uma olhada soquetes cpp, um wrapper C++ para as chamadas do sistema de soquetes.Funciona com vários sistemas operacionais (Win32, POSIX, Linux, *BSD).Não acho que funcione com 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 funciona bem em outros sistemas operacionais.

@Jax:O extern "C" coisa importa, muito mesmo.Se um arquivo de cabeçalho não tiver um, então (a menos que seja um arquivo de cabeçalho somente C++), você terá que incluir seu #include com isso:

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

Basicamente, sempre que um programa C++ quiser se conectar a recursos baseados em C, o extern "C" é vital.Em termos práticos, significa que os nomes usados ​​em referências externas não serão mutilados, como seriam os nomes normais em C++. Referência.

ISENÇÃO DE RESPONSABILIDADE:Não sou um programador C++, mas conheço C muito bem.Adaptei essas chamadas de algum código C que tenho.

Além disso, o markdown colocou esses _ estranhos como meus sublinhados.

Você deve ser capaz de escrever uma classe de abstração em torno dos soquetes C com algo assim:

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 mais ou menos assim:

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

A resposta é usar o sinalizador c89 a seguir:

 -D_OE_SOCKETS

Segue exemplo;

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

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top