Cara menggunakan C socket API di C ++ pada z / OS

158

Saya mengalami masalah mendapatkan C soket API untuk bekerja dengan baik di C++atas z/OS.

Meskipun saya termasuk sys/socket.h, saya masih mendapatkan kesalahan waktu kompilasi yang mengatakan kepada saya bahwa AF_INETtidak didefinisikan .

Apakah saya kehilangan sesuatu yang sudah jelas, atau apakah ini terkait dengan fakta bahwa dengan z/OSmenjadikan masalah saya jauh lebih rumit?


Pembaruan : Setelah diselidiki lebih lanjut, saya menemukan bahwa ada sesuatu #ifdefyang saya pukul. Tampaknya z/OStidak senang kecuali saya menentukan "jenis" soket yang saya gunakan dengan:

#define _OE_SOCKETS

Sekarang, saya pribadi tidak tahu untuk apa ini _OE_SOCKETSsebenarnya, jadi jika ada z/OSprogrammer soket di luar sana (kalian bertiga), mungkin Anda bisa memberi saya gambaran tentang bagaimana ini semua bekerja?


Aplikasi Uji

#include <sys/socket.h>

int main()
{
    return AF_INET;
}

Kompilasi / Tautan Keluaran:

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.

Pemeriksaan sys / sockets.h tidak termasuk definisi yang saya butuhkan, dan sejauh yang saya tahu, itu tidak diblokir oleh #ifdefpernyataan apa pun .

Namun saya perhatikan itu mengandung yang berikut:

#ifdef __cplusplus
  extern "C" {
#endif

yang pada dasarnya merangkum seluruh file? Tidak yakin apakah itu penting.

Jax
sumber

Jawaban:

86

Simpan salinan manual IBM:

Publikasi IBM pada umumnya sangat baik, tetapi Anda perlu membiasakan diri dengan format mereka, serta mengetahui ke mana harus mencari jawaban. Anda akan sering menemukan bahwa fitur yang ingin Anda gunakan dijaga oleh "makro uji fitur"

Anda harus meminta programmer sistem yang ramah untuk menginstal Referensi Perpustakaan Run-Time XL C / C ++: Halaman Man pada sistem Anda. Kemudian Anda dapat melakukan hal-hal seperti "man connect" untuk menarik halaman manual untuk socket connect () API. Ketika saya melakukan itu, inilah yang saya lihat:

FORMAT

X / Buka

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

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

Soket Berkeley

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

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

Saya tidak kesulitan menggunakan sockets API BSD di C ++, di GNU / Linux. Berikut contoh program yang saya gunakan:

#include <sys/socket.h>

int
main()
{
    return AF_INET;
}

Jadi pendapat saya tentang ini adalah bahwa z / OS mungkin merupakan faktor yang menyulitkan di sini, bagaimanapun, karena saya belum pernah menggunakan z / OS sebelumnya, apalagi diprogram di dalamnya, saya tidak dapat mengatakan ini secara definitif. :-P

Chris Jester-Young
sumber
32

Lihat bagian Menggunakan soket Layanan Sistem UNIX z / OS di Panduan Pemrograman z / OS XL C / C ++. Pastikan Anda menyertakan file header yang diperlukan dan menggunakan #define yang sesuai.

Tautan ke dokumen telah berubah selama bertahun-tahun, tetapi Anda harus dapat mencapainya dengan cukup mudah dengan menemukan lokasi saat ini dari bagian Dukungan & Unduhan di ibm.com dan mencari dokumentasi berdasarkan judul.

Robert Groves
sumber
26

_OE_SOCKETS tampaknya hanya untuk mengaktifkan / menonaktifkan definisi simbol yang terkait dengan soket. Tidak jarang di beberapa perpustakaan memiliki banyak makro untuk melakukan itu, untuk memastikan bahwa Anda tidak mengkompilasi / menghubungkan bagian-bagian yang tidak diperlukan. Makro tidak standar dalam implementasi soket lain, tampaknya sesuatu yang spesifik untuk z / OS.

Lihatlah halaman ini:
Kompilasi dan Menautkan Program Soket az / VM C

Fabio Ceconello
sumber
2
z / OS memiliki banyak kesamaan dengan z / VM seperti halnya Windows dengan Linux, jadi saya sedikit bingung mengapa Anda memposting tautan itu.
paxdiablo
Perhatikan bahwa makro _OE_SOCKETS muncul di keduanya, dan tampaknya memiliki tujuan yang sama. Yang tidak mengejutkan, karena mungkin IBM menggunakan basis kode yang sama untuk dukungan soket di kedua produk. Saya tidak bermaksud mengatakan bahwa dokumentasi z / VM berlaku untuk z / OS, itu hanya kasus yang paling mirip yang saya temukan.
Fabio Ceconello
1
Saya pikir itu hanya kebetulan. z / VM tidak menggunakan produk Lingkungan Bahasa z / OS, yang menyediakan file header yang relevan yang digunakan untuk melakukan panggilan soket.
Anthony Giorgio
25

Jadi coba

#define _OE_SOCKETS

sebelum Anda memasukkan sys / socket.h

fizzer
sumber
19

Anda mungkin ingin melihat ke soket cpp , pembungkus C ++ untuk panggilan sistem soket. Ia bekerja dengan banyak sistem operasi (Win32, POSIX, Linux, * BSD). Saya tidak berpikir itu akan bekerja dengan z / OS tetapi Anda dapat melihat pada file sertakan yang digunakannya dan Anda akan memiliki banyak contoh kode yang diuji yang bekerja dengan baik pada OS lain.

Federico
sumber
18

@ Jet: extern "C"Masalahnya sangat, sangat banyak. Jika file header tidak memilikinya, (kecuali file header C ++ - only), Anda harus menyertakannya #include:

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

Pada dasarnya, kapan pun di mana program C ++ ingin menautkan ke fasilitas berbasis C, hal extern "C"itu sangat penting. Dalam istilah praktis, ini berarti bahwa nama yang digunakan dalam referensi eksternal tidak akan hancur, seperti nama C ++ normal. Referensi.

Chris Jester-Young
sumber
14

PENOLAKAN: Saya bukan seorang programmer C ++, namun saya tahu C dengan sangat baik. Saya menyesuaikan panggilan ini dari beberapa kode C yang saya miliki.

Penurunan harga juga menempatkan _ aneh ini sebagai garis bawah saya.

Anda seharusnya bisa menulis kelas abstraksi di sekitar soket C dengan sesuatu seperti ini:

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

Kemudian punya metode untuk membuka, menutup, dan mengirim paket ke soket.

Misalnya, panggilan terbuka mungkin terlihat seperti ini:

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
sumber
Ini tidak ada hubungannya dengan pertanyaan aslinya.
Anthony Giorgio
13

Gunakan bendera c89 berikut:

 -D_OE_SOCKETS

Contoh:

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

Untuk informasi lebih lanjut, cari Opsi c89 di Panduan Pengguna z / OS XLC / C ++.

Hope T. Membantu
sumber