Operating System - OpenVMS
cancel
Showing results for 
Search instead for 
Did you mean: 

Cobol Sockets

 
SOLVED
Go to solution
Yyrkoon_
Advisor

Cobol Sockets

Hi there, guys,

I am trying to create a server socket using Cobol, but well... maybe say "trying" is too much, I have no **bleep** idea about how I can do that. I have found several examples in C, but no one in cobol. I have also seen the official VMS documentation which use to twist my mind... it did it again. I am sure that it can't be so difficult. Could you be so kind of giving me any example?

 

Thanks in advance.

11 REPLIES 11
Hoff
Honored Contributor
Solution

Re: Cobol Sockets

I'm not aware of any still-posted examples of using COBOL with TCP/IP Sockets and TCP or UDP communications via the sys$qio and sys$qiow calls.

There have been one or two folks asking similar questions in the last ~twenty years, so... this is unfortunately not something that's been very commonly discussed, either.

OpenVMS has not particularly joined the Stack Overflow era, and this unfortunately means that there are not examples of each and every OpenVMS call in each and every language posted all over the 'net.  Compounding this, the folks at HPE have largely retired their libraries of example code (AskQ et al disappeared a decade or two ago), and the folks at VSI have not yet created, accumulated and/or posted examples at the VSI site.   (The folks at HPE support might still have access to these examples, so a call to the folks there — if you have support access — might provide some materials.  Asking VSI support might encourage those folks to scrounge up some examples they likely have access to, too.)

So...

Most COBOL folks get to roll their own examples.   This is less involved than it might seem.   OpenVMS system service calls use similar argument-passing mechanisms across all calls (as documented in the calling standard), most commonly including pass-by-value, pass-by-reference, and itemlists passed by reference.   Examples of any of these argument passing mechanisms for any system service or RTL call are applicable across other services.  Which means collecting and reading apparently-unrelated system service examples is the foundation of this and pretty much anything involving COBOL on OpenVMS, as well as rummaging the archives of the comp.os.vms newsgroup, and rummaging existing examples of $qiow calls for examples such as using itemlists.  Also reading about how COBOL relates to these argument-passing mechanisms.

A related problem end-user folks will probably encounter here is with connection security and authentication, as the core mechanisms for this are emphatically not COBOL-friendly — very few folks are doing new socket programs without using SSL/TLS security.   There are shims that can potentially help with this.

 

Steven Schweda
Honored Contributor

Re: Cobol Sockets

> I am trying to create a server socket using Cobol, [...]

   Not a very helpful description of the actual task.

> [...] I have found several examples in C, but no one in cobol. [...]

   With my weak psychic powers, I can't see your "several examples in
C".

   Did you find "examples in C" using sys$qio[w]() or the (more
portable) C socket functions (accept(), bind(), socket(), ...)?  That
is, are the examples unhelpful because you need to translate their
sys$qio[w]() stuff from C to COBOL, or because you need to translate
their C socket functions to sys$qio[w]() in COBOL?

Yyrkoon_
Advisor

Re: Cobol Sockets

The examples I found were using sys$qio, you can see one of them HERE. About my description of "create a server socket"... well, not sure what you want, it's just that, I could tell you in some other ways, but at the end of the day it will mean "create a server socket" again.

I will take a look to the documents our kind first contributor attached, but reading the post I think they will only lead me astray, so if anyone else has anything a bit more concrete it will be awesome.

abrsvc
Respected Contributor

Re: Cobol Sockets

An alternative method may be to gataher existing routines and CALL them from Cobol.  I know of existing routines written in Fortran and others written in Macro32 that encompass the QIO routines you have seen into callable modules.  This might be easier.  Otherwise, a more descriptive list of what you are trying to accomplish might help.

If you are looking to have two Cobol programs talk to each other via sockets, then you will need routines to establish and use sockets for both receiving and transmittting.  If this is the case, I should be able to provide some example routines.  I have Fortran ones that do this that I can translate into Cobol if that would help.

Let me know.

Dan

Yyrkoon_
Advisor

Re: Cobol Sockets

Many thanks for the offer Dan, but nothing further from my intetion that making you work. I am currently using fortran routines, I have also done it using java. The real problem is not the communication thing, the issue is that "my whole" application is written in Cobol and I would like to rid of the other languages parts, they work perfectly and I can keep them as they are, it was just a desire, just in case some of you already have any example I can use, but it seems you don't.

 

Many thanks anyway to you all for your cooperation.

PS: Of course, Dan, if you are quite bored someday and you want to translate it I will be glad to take an eye to that code :)

JRBrady
Occasional Advisor

Re: Cobol Sockets

Hello, Ran across this thread while doing a web search for "openvms socket from cobol". A bit late to the party. :-(

I don't have specific examples of socket programming with COBOL, although it's something I want to do for a hobbyist project. In my investigation I looked at the libcurl port to OpenVMS. [Update] It is possible to link COBOL programs with LIBCURL, but many of the LIBCURL routines return pointers to values and to my knowledge COBOL doesn't provide a way to dereference the pointer and access the value(s). From the HP COBOL Reference Manual, page 245, "Because COBOL does not support dynamic allocation, there is no way to dereference the pointer and access the allocated data." Perhaps one of the experts in this forum can elaborate further? 

What might be an option is to write wrapper routines in C to expose the desired functions and link the wrappers with your COBOL program. Quite easy to do...I will look into this further for my project.

With regard to calling OpenVMS system services from COBOL, it's easy and fun! I wrote an COBOL program that runs as a detached process, sleeping until an event flag is trigged, grabs a message from a mailbox and writes to an Rdb database. Here's a couple of code snippets. Just follow the system service calling standards with equivalent COBOL datatypes and it works flawlessly. It it helps I'd be glad to share the code with you.

 

Compute Output-MBX-Function = IO$_READVBLK + IO$M_NOW
Compute Output-MBX-Setmode = IO$_SETMODE + IO$M_WRTATTN
Compute Input-MBX-Function = IO$_WRITEVBLK + IO$M_NOW +
                             IO$M_NORSWAIT

Perform Create-Input-Mailbox
Perform Create-Output-Mailbox

Call 'LIB$GET_EF' Using By Reference Timer-Event-Flag
                  Giving Status-Code
If Status-Code Is Failure
   Call 'LIB$STOP' Using By Value Status-Code
End-If

Call 'SYS$BINTIM' Using By Descriptor Countdown-Time-Delta
                        By Reference Countdown-Time-Binary
                 Giving Status-Code
If Status-Code Is Failure
   Call 'LIB$STOP' Using By Value Status-Code
End-If

Move 'ZR' to Input-MBX-Buffer
Move +2 to Input-MBX-Chars
Perform Write-To-Input-Mailbox

******************************************************************
* Set Countdown Timer to awaken process when timer expires.      *
* Because Countdown-Timer-AST pointer contains the actual AST    *
* routine address, By Value is used instead of By Reference as   *
* usually specified for this system service call.                *
******************************************************************
Set-Countdown-Timer.

Call 'SYS$SETIMR' Using By Value Timer-Event-Flag
                        By Reference Countdown-Time-Binary
                        By Value Countdown-Timer-AST
                        Omitted
                        Omitted
                 Giving Status-Code

If Status-Code Is Failure
   Call 'LIB$STOP' Using By Value Status-Code
   Set Program-Error to True
   Move 'Set-Countdown-Timer' to Error-Routine-Name
   Perform Exit-This-Program
End-If
.

 

Steven Schweda
Honored Contributor

Re: Cobol Sockets

> Hello, Ran across this thread while doing a web search for "openvms
> socket from cobol". A bit late to the party. :-(

   There's a vaguely related (and newer) thread at:

      http://community.hpe.com/t5/x/x/m-p/6884503

   It's FORTRAN/Fortran, not COBOL, and only gethostbyname(), not actual
socket I/O, but there are some mixed-language code examples which might
be of some interest.

   The principal advantage to using system services ($QIO, ...) is not
needing to drag a C compiler into a non-C environment.  A secondary
advantage is not needing to puzzle out how to deal with all the C
pointer exotica from a non-C program.  (With my near-total ignorance of
COBOL, either way is beyond my ken.)

JRBrady
Occasional Advisor

Re: Cobol Sockets

Hello Steven, interesting thread, although I don't know much about FORTRAN programming. Not sure how pointers would be handled in that language.

I updated my post above. COBOL can handle pointers but apparently cannot dereference them to access what they point to (page 245 of the COBOL Reference Manual). Does FORTRAN?

This may not help the FORTRAN user, but in COBOL it's very easy to call the SYS$QIO/W (and other OpenVMS system service and library) routines. Here's an example. Not related to sockets, but hopefully of help to a future viewer.

      ******************************************************************
      * Read From Mailbox                                              *
      ******************************************************************
       Read-From-Mailbox.
 
           Move Spaces to MBX-Buffer

           Call 'SYS$QIOW' Using Omitted
                                 By Value MBX-Channel
                                 By Value MBX-Function
                                 By Reference MBX-IO-Status-Block
                                 Omitted
                                 Omitted
                                 By Reference MBX-Buffer
                                 By Value MBX-Buffer-Size 
                                 Omitted
                                 Omitted
                                 Omitted
                                 Omitted
                          Giving Status-Code

           Evaluate True
               When Status-Code is Failure
                    Display '*** Call to SYS$QIOW failed (status).'
                    Call 'LIB$STOP' Using By Value Status-Code
               When IOSB-Status Is Failure
                    Display '*** Call to SYS$QIOW failed (IOSB).'
                    Call 'LIB$STOP' Using By Value IOSB-Status
               When Other
                    Perform Get-Time-Stamp
                    Move IOSB-Count to Longword-Display
                    Display Time-Stamp ' Command [' MBX-Buffer(1:1)
                            '] bytes received = ' Longword-Display
                    Perform Display-Mailbox-Message
                    If MBX-Buffer(1:1) = 'X' or 'x'
                       Set Exit-Program to True
                    End-If
           End-Evaluate
           .

 

Steven Schweda
Honored Contributor

Re: Cobol Sockets

> [...] COBOL can handle pointers but apparently cannot dereference them
> to access what they point to (page 245 of the COBOL Reference Manual).

   That's a pretty limited interpretation of "can handle".  ("page 245
of the COBOL Reference Manual" is not a useful reference, by the way.)

> Does FORTRAN?

   After a fashion, at least.  Without using a POINTER statement, you
can have a function/subroutine which believes that it's getting an
argument by reference, but you can pass it an address by value.

   The POINTER statement seems to add a more natural way to deal with
pointers, but it's still too new to me for me to explain it.  (And
there's an old DEC-language-extension style, and a new Fortran-99 style.
I largely quit using Fortran before '99, so I know nothing.  My example
programs in that other topic already exceed my understanding.)

JRBrady
Occasional Advisor

Re: Cobol Sockets

In case anyone's interested, as a follow-up to my previous post, yes, the world of LIBCURL is available to COBOL programs...with one caveat - a C wrapper routine is apparently required. See below.

Here are the results of testing on an AlphaStation running OpenVMS 8.4 with LIBCURL 7.47 installed.

Before we begin, we must define our C compiler include logical name to handle "#include <curl.h>". Then, create an options file for the linker to reference the LIBCURL installed shareable image.

$DEFINE/PROCESS DECC$SYSTEM_INCLUDE GNV$CURL_INCLUDE

$EDIT LIBCURL.OPT
GNV$LIBCURL/SHAREABLE
<CTRL-Z>

First test - can we call one of the LIBCURL functions from C? Keep it simple; curl_version returns a pointer to an informational, null-delimited string. If this works, we have the ability to create a wrapper routine around the various LIBCURL functions.

$EDIT C2CCTEST1.C
#include <curl.h>
#include <stdio.h>

extern char *curl_version();

int main()
{
    char *verstr;

    verstr = curl_version();
    printf("Curl version: %s\n",verstr);

    return(0);
}
<CTRL-Z>

$CC C2CTEST1.C
$LINK C2CTEST1,LIBCURL/OPT
RUN C2CTEST1
Curl version: libcurl/7.47.0 OpenSSL/0.9.8h zlib/1.2.8

Second test - can we call the wrapper routine from our COBOL program? The answer is yes, but some manipulation of the LIBCURL results are necessary, as COBOL apparently cannot dereference pointers to access the data. C is exquisitely equipped to handle said dereferencing... :-) Are there better ways to pass data between two character pointer variables?

$EDIT C2C_TEST2_C.C
#include <curl.h>
#include <stdio.h>
#include <string.h>

extern char *curl_version();

int c2c_curl_version(char *ver_str_ptr)
{
    strcpy(ver_str_ptr, curl_version());

    printf("C program version    : %s\n",ver_str_ptr);

    return(0);
}
<CTRL-Z>


$EDIT C2C_TEST2_COBOL.COB
       Identification Division.
       Program-ID.    C2C_TEST2_COBOL.

       Environment Division.
       Configuration Section.
       Source-Computer. AXP.
       Object-Computer. AXP.

       Data Division.
       Working-Storage Section.
       01   General-Variables.
            03 Version-String     Pic X(100) Value Spaces.
            03 Status-Code        Pic S9(9) Comp.

       Procedure Division.
       Main-Routine.

            Call 'c2c_curl_version' Using By Reference Version-String
                                   Giving Status-Code

            Display 'COBOL program version: ' Version-String

            Exit Program
            .
<CTRL-Z>

$CC C2C_TEST2_C.C
$COBOL/ANSI C2C_TEST2_COBOL.COB
$LINK C2C_TEST2_COBOL,C2C_TEST2_C,LIBCURL/OPT
$RUN C2C_TEST2_COBOL

C program version    : libcurl/7.47.0 OpenSSL/0.9.8h zlib/1.2.8
COBOL program version: libcurl/7.47.0 OpenSSL/0.9.8h zlib/1.2.8

Yes! We are able to obtain the desired result. Of course, the more complex functions require more thought and code, but at least we know it's possible. HTH...

JRBrady
Occasional Advisor

Re: Cobol Sockets

>> That's a pretty limited interpretation of "can handle".  ("page 245
of the COBOL Reference Manual" is not a useful reference, by the way.)

Sorry, I omitted my laboriously-typed out quote! Doesn't everyone have a copy of the gi-normous Reference Manuals handy? LOL I don't either...PDF. Here's the quote:

""You can also use an appropriate system service or the Run-Time Library routine LIB$GET_VM_64 to allocate data and store the address in the pointer variable. Because COBOL does not support dynamic allocation, there is no way to dereference the pointer and access the allocated data. However, you can pass the pointer to other languages that require a 64-bit pointer in a 64-bit address space."

> Does FORTRAN?

>> After a fashion, at least.  Without using a POINTER statement, you
can have a function/subroutine which believes that it's getting an
argument by reference, but you can pass it an address by value.

>>The POINTER statement seems to add a more natural way to deal with
pointers, but it's still too new to me for me to explain it.  (And
there's an old DEC-language-extension style, and a new Fortran-99 style.
I largely quit using Fortran before '99, so I know nothing.  My example
programs in that other topic already exceed my understanding.)

Appreciate the info. I barely scratched the surface with FORTRAN years ago, but good to know.