Como usar a API do soquete C em C++ no z/OS
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.
Solução
Mantenha uma cópia dos manuais da IBM à mão:
- Guia de programação C/C++ do z/OS V1R11.0 XL
- Referência da Biblioteca de Tempo de Execução z/OS V1R11.0 XL C/C++
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++.