Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Sharing a TCP socket between images

55 views
Skip to first unread message

Albrecht Schlosser

unread,
Mar 31, 2011, 10:29:31 AM3/31/11
to
"Sharing" might not be the right word in this case, but
anyway: what I want to achieve is that one image uses a
TCP socket, reads/writes data, and then, depending on the
data read, runs another image that uses the existing
socket connection. The first image should exit immediately
(or short) after starting image #2. If this is not possible,
I could live with keeping the first image active, until
image #2 terminates.

This could be thought of like fork/exec in Unix, where the
forked process shares all existing open files/sockets.

What I did so far with some limited success: I created a
TCP service, and the TCP service starts a DCL procedure.
In this procedure I can read/write data from/to the socket
by opening a file with the logical name SYS$NET [1]. I'm
sure this is documented somewhere, but I don't know where
right now, and it works.

Then, after reading some data (and opt. writing a reply),
the DCL procedure can run an image, and in this image I can
connect the socket as usual [2]. This is also documented
for TCP/IP services and works fine.

What I want to do: replace the DCL read/write part with another
image invocation to get better control over the socket. One point
that I want to solve is (among others) that "$ read/timeout" seems
not to work when reading from sockets (see below[1]). It doesn't
go to the error label (omitted below for clarity).

Does anybody have an idea how this can be solved, or can this
definitely not be done?

Thanks in advance for all thoughts and ideas.

Albrecht

-----------------------------------------------------------
[1] Excerpt from the DCL procedure, started by TCP service:
--- snip ---
$ open/read/write file sys$net
$ read/timeout=10/err=init_error file temp
$! ...
$ write file "END"
$ close file
$!
$ run/nodeb something.exe
--- snip ---

---------------------------------------------
[2] Opening the TCP socket in "service mode":
--- snip ---
sock = socket (TCPIP$C_AUXS, 0, 0);
--- snip ---

Pierre

unread,
Mar 31, 2011, 10:47:28 AM3/31/11
to
as I never tested it, this may be absolute nonsense but wouldn't it be
possible to open SYS$NET in share mode, in your images also use SYS
$NET also in share mode, then close it at the end of the DCL routine ?

Albrecht Schlosser

unread,
Mar 31, 2011, 11:12:41 AM3/31/11
to

Thanks for the reply and the idea, but I'm not opening a file in
my image(s), it's a TCP socket, with standard (BSD) socket functions
(not with VMS $QIO and such). Opening it as a file in the DCL proc.
was only for testing/demonstration. I assume that DCL does some /magic/
to open the underlying socket.

BTW: It's somewhat special anyway, since the "TCP/IP AUX Server" (or
something named similarly) accepts the incoming connect request and
transfers it /somehow/ to the DCL procedure and the started image in
my posted procedure.

I'd like to know how I can utilize this /magic/ to use the socket in
more than one image w/o closing the TCP socket connection. But maybe
I'm dreaming...

Albrecht

Jan-Erik Soderholm

unread,
Mar 31, 2011, 11:14:43 AM3/31/11
to

You should be able to simply open SYS$NET from any tool (DCL, C, whatever).
I guess... :-)

Bob Gezelter

unread,
Mar 31, 2011, 12:10:15 PM3/31/11
to

Albrecht,

Before going any further, which IP package is being used (and which
release)?

- Bob Gezelter, http://www.rlgsc.com

Albrecht Schlosser

unread,
Mar 31, 2011, 6:28:46 PM3/31/11
to
On 31.03.2011 18:10, Bob Gezelter wrote:

> Before going any further, which IP package is being used (and which
> release)?

$ tcpip sho vers

HP TCP/IP Services for OpenVMS Industry Standard 64 Version V5.6 - ECO 2
on an HP rx2660 (1.42GHz/6.0MB) running OpenVMS V8.3-1H1


We're always using HP TCP/IP, and almost all of our customers' systems
are on the same system versions as shown above, but a few may still be
VMS 8.2-something. However, 8.3-1H1 and TCP/IP 5.6 or higher would be
okay. We do not use VMS 8.4 yet.

Sorry for not mentioning this before.

Thanks so far, Bob...

Albrecht

BillPedersen

unread,
Mar 31, 2011, 7:35:40 PM3/31/11
to
On Mar 31, 10:29 am, Albrecht Schlosser <ajs856S...@go4more.de> wrote:
> "Sharing" might not be the right word in this case, but
> anyway: what I want to achieve is that one image uses a
> TCP socket, reads/writes data, and then, depending on the
> data read, runs another image that uses the existing
> socket connection. The first image should exit immediately
> (or short) after starting image #2. If this is not possible,
> I could live with keeping the first image active, until
> image #2 terminates.

I believe what you are talking about here is different than sharing a
port. It is really the serial reuse of the link/device associated
with the process by multiple images running serially in the process.

There is a facility within HP TCP/IP to SHARE a socket between
processes. This is controlled by the SO_REUSEPORT and SO_SHARE
options as documented in the HP TCP/IP manual: Sockets API and System
Services Programming (http://h71000.www7.hp.com/doc/82final/6529/
ba548-90002.pdf).

Bill.

Albrecht Schlosser

unread,
Mar 31, 2011, 8:18:05 PM3/31/11
to
On 01.04.2011 01:35, BillPedersen wrote:

> On Mar 31, 10:29 am, Albrecht Schlosser<...> wrote:
>> "Sharing" might not be the right word in this case, but
>> anyway: what I want to achieve is that one image uses a
>> TCP socket, reads/writes data, and then, depending on the
>> data read, runs another image that uses the existing
>> socket connection. The first image should exit immediately
>> (or short) after starting image #2. If this is not possible,
>> I could live with keeping the first image active, until
>> image #2 terminates.
>
> I believe what you are talking about here is different than sharing a
> port. It is really the serial reuse of the link/device associated
> with the process by multiple images running serially in the process.

Yes, that sounds exactly like what I want to do. But if this was not
possible, then I could imagine that "sharing" a socket between two
/processes/, where always only one of them controls the socket, while
the other process is waiting, would be an option as well.

> There is a facility within HP TCP/IP to SHARE a socket between
> processes. This is controlled by the SO_REUSEPORT

Hmm, SO_REUSEPORT: "Allows more than one process to receive UDP
datagrams destined for the same port." That's not what I need, if
it is only for UDP (I need TCP).

> and SO_SHARE

The only mention of SO_SHARE I found in the manual is: "Allows multiple
processes to share the socket." But how would I do this?

> options as documented in the HP TCP/IP manual: Sockets API and System
> Services Programming (http://h71000.www7.hp.com/doc/82final/6529/
> ba548-90002.pdf).

Thanks for your help.

Albrecht

glen herrmannsfeldt

unread,
Mar 31, 2011, 11:39:08 PM3/31/11
to
BillPedersen <pede...@ccsscorp.com> wrote:
(snip)

> There is a facility within HP TCP/IP to SHARE a socket between
> processes. This is controlled by the SO_REUSEPORT and SO_SHARE
> options as documented in the HP TCP/IP manual: Sockets API and System
> Services Programming (http://h71000.www7.hp.com/doc/82final/6529/
> ba548-90002.pdf).

I have known sharing for UDP, but it isn't so obvious
that it can be done with TCP.

-- glen

Richard Whalen

unread,
Apr 1, 2011, 10:48:05 AM4/1/11
to
It sounds like you are trying to hand-off a socket from one process to
another.
TCP/IP Services also refers to the as using the auxiliary listener.

http://h71000.www7.hp.com/doc/73final/6529/6529pro_025.html

May help you get started.


Jose Baars

unread,
Apr 1, 2011, 4:32:12 PM4/1/11
to

Hi,

I am curious,too. I did the same you did, creating a service
and using an executable that opened TCPIP$C_AUXS.

After the first image finished, the bgdevice sys$net pointed
to was gone, so the second image wasn't able to open
anything.

So, I thought being clever, and the first thing I did in the
procedure ucx calls per the service definition, was an
open/write/share of sys$net.

Now the bgdevice survived after the first image
execution, but the second image called failed at the
socket( TCPIP$C_AUXS,SOCK_STREAM,0) call
with BADPARAM.
A write to sys$net by DCL after that was succesful.

So you can read and write in the second image to the
device, by opening the bgdevice or sys$net for read/write,
but not use clever socket functions like select(), which
until now, don't work on anything but actual sockets
on OpenVMS, not on file descriptors. Also, if your
second image does a socket() call it will fail.

It looks like doing this using TCPIP$C_AUXS doesn't
work, something is seriously destroyed when closing
the socket or running down the image.

An example what SO_SHARE and/or
SO_REUSEADDR might do:

http://h71000.www7.hp.com/wizard/wiz_3995.html

or here:

http://vouters.dyndns.org/tima/Windows-OpenVMS-Accessing-your-VMS-prompt-from-your-PC.html

Definitely not what you are after.
Hopefully someone in the know has more useful
information.

Richard Maher

unread,
Apr 1, 2011, 7:26:21 PM4/1/11
to

"Jose Baars" <peut...@googlemail.com> wrote in message
news:381c4004-ea8d-4135...@j13g2000pro.googlegroups.com...

Don't know how useful it will be but if you search this group for "maher
ucx$c_share" there are some related posts.

Regards Richard Maher


Albrecht Schlosser

unread,
Apr 2, 2011, 1:03:13 PM4/2/11
to

Thanks, but this is the part that I knew and that works well.

The tricky part is to do the same with two images running one after
the other (or in parallel), using the same socket connection.

Albrecht

Albrecht Schlosser

unread,
Apr 2, 2011, 1:12:13 PM4/2/11
to
On 01.04.2011 22:32, Jose Baars wrote:

> I am curious,too. I did the same you did, creating a service
> and using an executable that opened TCPIP$C_AUXS.
>
> After the first image finished, the bgdevice sys$net pointed
> to was gone, so the second image wasn't able to open
> anything.
>
> So, I thought being clever, and the first thing I did in the
> procedure ucx calls per the service definition, was an
> open/write/share of sys$net.
>
> Now the bgdevice survived after the first image
> execution, but the second image called failed at the
> socket( TCPIP$C_AUXS,SOCK_STREAM,0) call
> with BADPARAM.
> A write to sys$net by DCL after that was succesful.

What does successful mean in detail? Did it reach the client
side, or did it only not return an error?

> So you can read and write in the second image to the
> device, by opening the bgdevice or sys$net for read/write,
> but not use clever socket functions like select(), which
> until now, don't work on anything but actual sockets
> on OpenVMS, not on file descriptors. Also, if your
> second image does a socket() call it will fail.

That's what I suspected. :-(

> It looks like doing this using TCPIP$C_AUXS doesn't
> work, something is seriously destroyed when closing
> the socket or running down the image.

I'd suspect that closing the socket explicitly or when
running down the image would end the socket connection
by sending the TCP FIN flag, but maybe this can be suppressed
by using SO_SHARE ?

> An example what SO_SHARE and/or
> SO_REUSEADDR might do:
>
> http://h71000.www7.hp.com/wizard/wiz_3995.html

Yep, meanwhile I found this too, but it is not the same I want
to do. I'll have to check this further...

Thanks for sharing your experiences. This is likely to save
some work for me.

> Hopefully someone in the know has more useful
> information.

That would be fine.

Albrecht

Jose Baars

unread,
Apr 2, 2011, 2:06:50 PM4/2/11
to
On Apr 2, 7:12 pm, Albrecht Schlosser <ajs856S...@go4more.de> wrote:
>I'd suspect that closing the socket explicitly or when
>running down the image would end the socket connection
>by sending the TCP FIN flag, but maybe this can be suppressed
>by using SO_SHARE ?

No, tried that, against better judgement.Sharing means using
simultaneously, not consecutively.

Jose Baars

unread,
Apr 4, 2011, 1:06:10 PM4/4/11
to

Hi,

I found a way to start two images consecutively
in a DCL procedure called by the TCPIP auxiliary
services. You need access to sources of both
executables, as I do something intentionally wrong,
or undocumented anyway.

Hard to post source code and keep
it readable using Google, so here a desciption:

In the DCL procedure I start with this:

$ open/share/write snet sys$net

(see log below for the procedure) to prevent TCP/IP
throwing away the channel
at image rundown of the first time you execute

I the executable I open a channel with sys$assign:

status = sys$assign( &bgdescriptor, &ipchannel, 0,0,0);

Then I do NOT do a sys$qiow SETMODE, which would fail
when called in the second image. According to the docs
and all examples, this should be done, but I don't.

Then I call
s = decc$socket_fd( ipchannel );

After that, I use socket calls to communicate, like
setsockopt, recv etc.

Below a a log:

$ set noon
$!
$ crlf = f$fao("!/")
$ serialsrv := $user:[jose.serialsrv]serialsrv
$!
$ open/share/write snet sys$net
$!
$ write snet "hello, starting first executable!", crlf
$!
$ usebg = f$trnlnm( "sys$net" )
$ serialsrv "Hi! This is the first image"
Using device _BG2064:
Opened channel 208, status = 1
Received [
Hi! This is the first image␍
]
$!
$ write snet "and now, starting second executable!", crlf
$ serialsrv "This is the second image"
Using device _BG2064:
Opened channel 208, status = 1
Received [
This is the second image␍
]
$!
$write snet "No more executables, bye!", crlf

Albrecht Schlosser

unread,
Apr 5, 2011, 7:03:01 AM4/5/11
to
On 04.04.2011 19:06, Jose Baars wrote:

> I found a way to start two images consecutively
> in a DCL procedure called by the TCPIP auxiliary
> services.

That's great, thank you! :-)

> You need access to sources of both
> executables, as I do something intentionally wrong,
> or undocumented anyway.

No problem.

> In the DCL procedure I start with this:
>
> $ open/share/write snet sys$net
>
> (see log below for the procedure) to prevent TCP/IP
> throwing away the channel
> at image rundown of the first time you execute
>
> I the executable I open a channel with sys$assign:
>

> status = sys$assign(&bgdescriptor,&ipchannel, 0,0,0);


>
> Then I do NOT do a sys$qiow SETMODE, which would fail
> when called in the second image. According to the docs
> and all examples, this should be done, but I don't.

I suspect that this is not needed, because you already
opened the device *shared* in the DCL procedure...

> Then I call
> s = decc$socket_fd( ipchannel );

Yeah, I had found this somewhere, too. That was another question
I had before: how to switch from qio to socket mode and vice versa?
The other way is done with vaxc$get_sdc(), BTW.

I was about to try another approach: start one image in the
DCL procedure and execute the other one from the first as a
subprocess. Then close the I/O channel in the first one after
some time (enough to open the shared I/O channel in the 2nd
image).

Another option I was (and am still) considering is to start
the 2nd image as a detached process to get rid of the first
process once the 2nd one has opened the channel. The first
image (and the DCL procedure) would then be able to exit
once the 2nd image in the detached process has taken over
the socket.

I still have to test this, but now I need to do something
else first. I'll report here when (if) I found a working
solution.

Thanks to all that replied and shared their ideas, links,
code, ...

--
Regards,
Albrecht

Jose Baars

unread,
Apr 6, 2011, 7:27:27 AM4/6/11
to
On Apr 5, 1:03 pm, Albrecht Schlosser <ajs856S...@go4more.de> wrote:

Short update: the last image you start in a procedure set up like
this
can open sockets in the documented way, which means you don't need
to change it or have access to the source code.

Jose Baars

unread,
Apr 7, 2011, 7:25:03 PM4/7/11
to
Op 4/6/2011 1:27 PM, Jose Baars schreef:
fwiiw, the code I used to test:


/* How to run more executables in an TCPIP$AUXS
DCL procedure.
this is the example commandprocedure

$ set noon
$!
$ crlf = f$fao("!/")

$ serialsrv := $dcs:[dcsjobaa.serialsrv]serialsrv


$!
$ open/share/write snet sys$net
$!
$ write snet "hello, starting first executable!", crlf
$!
$ usebg = f$trnlnm( "sys$net" )
$ serialsrv "Hi! This is the first image"

$!
$ delete/sym usebg


$ write snet "and now, starting second executable!", crlf
$ serialsrv "This is the second image"

$!
$write snet "No more executables, bye!", crlf

$exit

*/


#include <socket.h>
#include <unixio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <tcpip$inetdef.h>
#include <unistd.h>
#include <in.h>
#include <netdb.h>
#include <inet.h>
#include <time.h>

#include <starlet.h>
#include <descrip.h>
#include <efndef.h>
#include <iodef.h>

typedef struct IosbStruct{
unsigned short cond_value;
unsigned short count;
void *info;
} iosb, *iosbPtr;

typedef struct SocketParamStruct{
unsigned short protocol;
unsigned char type;
unsigned char family;
} socketparam, *socketparamPtr;

/* translate an errno or a vaxc$errno
if set to a VMS statuscode
* After a discussion in c.o.v:
* http://groups.google.com/group/
comp.os.vms/browse_thread/thread/
eb2a2950d162f899/c92d272553c7972d?
hl=nl%3Dc90cf9a9ff7d5142&
*/

#include <errno.h>
#include <errnodef.h>
#include <stsdef.h>

#ifdef EABANDONED
#define DECC$ERRNO_TO_MSGCOD(x) (x <= EBADMSG ? C$_EPERM+((x-1)<<STS$V_CODE) \
: C$_EABANDONED+((x-1-EBADMSG)<<STS$V_CODE) )
#else
#define DECC$ERRNO_TO_MSGCOD(x) ( C$_EPERM+((x-1)<<STS$V_CODE) )
#endif

#define VERROR ( vaxc$errno != 0 ? vaxc$errno : DECC$ERRNO_TO_MSGCOD(errno) )


main(int argc, char **argv)
{
int s;
int status;
int on = 1, off=0;
int thislen,totlen,asklen;
char message[84];
char bgdevicename[32];
struct dsc$descriptor_s bgdescriptor ={
0, /* dsc$w_length */
DSC$K_DTYPE_T, /* dsc$b_dtype */
DSC$K_CLASS_S, /* dsc$b_class */
bgdevicename /* dsc$a_pointer */
};
unsigned short ipchannel;
socketparam spar;
iosb sblock;

/* create a symbol usebg like usebg = f$trnlnm("sys$net")
* to defeat normal socket processing.
*/

if ( getenv( "usebg" ) != NULL ){

strcpy( bgdevicename, getenv( "usebg" ) );
bgdescriptor.dsc$w_length = (short) strlen( bgdevicename );

printf("Using device %s\n", bgdevicename);

status = sys$assign( &bgdescriptor, &ipchannel, 0,0,0);

if ( !(status&1) ){
printf("Error in sys$assign %s\n", bgdevicename);
return (VERROR);
}

printf("Opened channel %d\n", ipchannel);
/* we just pretend we haven't read the
* documentation and skip this
*
* spar.protocol = TCPIP$C_TCP;
* spar.type = TCPIP$C_STREAM;
* spar.family = TCPIP$C_AUXS;
*
* status = sys$qiow( EFN$C_ENF,
* ipchannel,
* IO$_SETMODE,
* &sblock,
* 0, 0,
* &spar,
* 0, 0, 0, 0, 0);
*
* if( !(status&1) || !(sblock.cond_value&1) ){
* printf("Error creating socket status = %d, iosb condition %d\n",
* status, sblock.cond_value);
* return( (status&1)?sblock.cond_value:status );
* }
*
* end of skip
*/

s = decc$socket_fd( ipchannel );

}else{

printf("Using standard socket call to open TCPIP$AUX socket\n");

s = socket(TCPIP$C_AUXS, SOCK_STREAM, 0);
if ( s < 0 ) {
printf("Error opening TCPIP$C_AUXS socket\n");
return( VERROR );
}
}

sprintf(message,"\r\n%.80s\r\n", argv[1] );
asklen = strlen( message );

for ( thislen = 0, totlen = 0 ; totlen < asklen; totlen += thislen ){
thislen = write(s , ( message + totlen), asklen );
if ( thislen < 0 ) {
close( s );
return( VERROR );
}
}

if ( recv(s, message, sizeof( message ), 0) < 0 ){
printf("Failed to receive data\n");
close(s);
return ( VERROR);
}

printf("Received [%s]\n", message );

close(s);
return(1);
}

0 new messages