Jak używać interfejsu API gniazda C w języku C ++ w systemie z / OS

158

Mam problemy uzyskiwanie c gniazd API do pracy odpowiednio w C++dniu z/OS.

Chociaż włączam sys/socket.h, nadal pojawiają się błędy czasu kompilacji, które mówią mi, że AF_INETnie jest zdefiniowane .

Czy brakuje mi czegoś oczywistego, czy jest to związane z faktem, że bycie na z/OSłóżku znacznie komplikuje moje problemy?


Aktualizacja : Po dalszym dochodzeniu odkryłem, że jest coś #ifdef, co uderzam. Najwyraźniej z/OSnie jest zadowolony, chyba że zdefiniuję z jakim „typem” gniazdek korzystam:

#define _OE_SOCKETS

Osobiście nie mam pojęcia, do czego to _OE_SOCKETSwłaściwie służy, więc jeśli z/OSsą tam jacyś programiści gniazd (wszyscy trzej), może moglibyście dać mi podsumowanie, jak to wszystko działa?


Aplikacja testowa

#include <sys/socket.h>

int main()
{
    return AF_INET;
}

Kompilacja / łącze wyjściowe:

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.

Sprawdzenie sys / sockets.h zawiera definicję, której potrzebuję, i o ile wiem, nie jest ona blokowana przez żadne #ifdefinstrukcje.

Zauważyłem jednak, że zawiera:

#ifdef __cplusplus
  extern "C" {
#endif

która zawiera w zasadzie cały plik? Nie jestem pewien, czy to ma znaczenie.

Jax
źródło

Odpowiedzi:

86

Zachowaj pod ręką kopię podręczników IBM:

Publikacje IBM są generalnie bardzo dobre, ale trzeba przyzwyczaić się do ich formatu, a także wiedzieć, gdzie szukać odpowiedzi. Dość często zauważysz, że funkcja, której chcesz użyć, jest chroniona przez „makro testu funkcji”

Powinieneś poprosić swojego przyjaznego programistę systemowego o zainstalowanie XL C / C ++ Run-Time Library Reference: Man Pages w twoim systemie. Następnie możesz zrobić takie rzeczy, jak „man connect”, aby wyświetlić stronę podręcznika dla funkcji API gniazda connect (). Kiedy to robię, widzę to:

FORMAT

X / Otwórz

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

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

Gniazda Berkeley

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

int connect(int socket, struct sockaddr *address, int address_len);
Anthony Giorgio
źródło
38

Nie miałem problemu z używaniem API gniazd BSD w C ++ w systemie GNU / Linux. Oto przykładowy program, którego użyłem:

#include <sys/socket.h>

int
main()
{
    return AF_INET;
}

Więc moim zdaniem z / OS jest prawdopodobnie czynnikiem komplikującym to tutaj, jednak ponieważ nigdy wcześniej z / OS nie korzystałem, a tym bardziej nie zaprogramowałem go, nie mogę tego powiedzieć definitywnie. :-P

Chris Jester-Young
źródło
32

Zobacz sekcję Korzystanie z gniazd usług systemowych z / OS UNIX w podręczniku programowania z / OS XL C / C ++. Upewnij się, że dołączasz niezbędne pliki nagłówkowe i używasz odpowiednich #defines.

Łącze do dokumentu zmieniało się na przestrzeni lat, ale dostęp do niego powinien być łatwy, znajdując aktualną lokalizację sekcji Pomoc techniczna i pliki do pobrania w witrynie ibm.com i przeszukując dokumentację według tytułu.

Robert Groves
źródło
26

_OE_SOCKETS wydaje się po prostu włączać / wyłączać definicję symboli związanych z gniazdami. Często zdarza się, że w niektórych bibliotekach jest do tego kilka makr, które zapewniają, że nie kompilujesz / nie łączysz niepotrzebnych części. Makro nie jest standardowe w innych implementacjach gniazd, wydaje się być czymś specyficznym dla systemu z / OS.

Spójrz na tę stronę:
Kompilowanie i łączenie programu z / VM C Sockets

Fabio Ceconello
źródło
2
System z / OS ma tyle samo wspólnego z z / VM, co Windows z Linuksem, więc jestem trochę zdezorientowany, dlaczego opublikowałeś ten link.
paxdiablo
Zwróć uwagę, że makro _OE_SOCKETS pojawia się w obu i wydaje się mieć ten sam cel. Co nie jest zaskakujące, ponieważ prawdopodobnie IBM używał tej samej bazy kodu do obsługi gniazd w obu produktach. Nie zamierzałem powiedzieć, że dokumentacja z / VM dotyczy z / OS, to po prostu najbardziej podobny przypadek, jaki znalazłem.
Fabio Ceconello
1
Myślę, że to tylko zbieg okoliczności. z / VM nie używa produktu z / OS Language Environment, który udostępnia odpowiednie pliki nagłówkowe używane do wywoływania gniazd.
Anthony Giorgio
25

Więc spróbuj

#define _OE_SOCKETS

przed dołączeniem sys / socket.h

fizzer
źródło
19

Możesz rzucić okiem na cpp-sockets , opakowanie C ++ dla wywołań systemowych gniazd. Działa z wieloma systemami operacyjnymi (Win32, POSIX, Linux, * BSD). Nie sądzę, że będzie działać z systemem z / OS, ale możesz przyjrzeć się plikom dołączanym, których używa, i będziesz mieć wiele przykładów przetestowanego kodu, który działa dobrze w innych systemach operacyjnych.

Federico
źródło
18

@Jax: Ta extern "C"sprawa ma bardzo duże znaczenie. Jeśli plik nagłówkowy go nie ma, to (chyba że jest to plik nagłówkowy tylko w C ++), musiałbyś go nim załączyć #include:

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

Zasadniczo zawsze, gdy program C ++ chce łączyć się z obiektami opartymi na języku C, extern "C"jest to niezbędne. W praktyce oznacza to, że nazwy używane w odnośnikach zewnętrznych nie zostaną zniekształcone, tak jak normalne nazwy w C ++. Odniesienie.

Chris Jester-Young
źródło
14

ZRZECZENIE SIĘ: Nie jestem programistą C ++, ale znam go naprawdę dobrze. Dostosowałem te wywołania z jakiegoś kodu C.

Również markdown umieścił te dziwne _ jako moje podkreślenia.

Powinieneś być w stanie napisać klasę abstrakcji wokół gniazd C za pomocą czegoś takiego:

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

Następnie przygotuj metody otwierania, zamykania i wysyłania pakietów przez gniazdo.

Na przykład otwarte zaproszenie może wyglądać mniej więcej tak:

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
źródło
To nie ma nic wspólnego z pierwotnym pytaniem.
Anthony Giorgio
13

Odpowiedź brzmi: użyj flagi c89, która jest następująca:

 -D_OE_SOCKETS

Oto przykład;

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

Aby uzyskać więcej informacji, poszukaj opcji C89 w podręczniku użytkownika z / OS XLC / C ++.

Hope T. pomaga
źródło