HP OpenVMS Systems

ask the wizard
Content starts here

Sharing Sockets?

» close window

The Question is:

 
Hi,
 
Question to UCX:(SO_SHARE)
 
can you tell me
how to use the SO_SHARE - Flag
 
const int on;
 
setsockopt(socket,SOL_SOCKET,SO_SHARE,&on, sizeof(on));
 
and
which OpenVMS-Versions(AXP,VAX) and UCX-Version
support the SO_SHARE - Parameter
at the setsockopt-Function
 
 
 


The Answer is :

 
  Please contact the Compaq Customer Support Center -- be prepared
  to indicate what you are expecting to use the SO_SHARE option for.
 
  Use of the auxillary server, for instance, might be the best
  approach to solving your particular problem.
 
  Attached is an example of using the $qio interface to share the
  socket between a parent process and a child.
 
  The underlying options have been around for quite some time,
  and the particular code below dates back to (at least) the
  TCP/IP Services V3.3 release.
 
 
/* PARENT.C */
#include <in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <starlet.h>
#include <lib$routines.h>
#include <descrip.h>
#include <dvidef.h>
#include <iodef.h>
#include <clidef.h>
#include <ucx$inetdef.h>        /* Provided during UCX installation */
 
/* Convert short port number from host to network byte order */
#define htons(x) ((unsigned short)((x<<8)|(x>>8)))
 
int status, reset_timer = FALSE; unsigned long timadr[2], timer_id;
 
void timer_ast(int x)
 
  if (reset_timer)
  {
    reset_timer = FALSE;
    if (!((status = sys$setimr(0, timadr, timer_ast, timer_id, 0)) & 1))
        lib$stop(status);
  }
  else
  {
    printf("Server timed out waiting for client connection\n");
    exit(1);
  }
 
 
unsigned long ucx_bg_unit(unsigned short chan)
 
    unsigned long item_code = DVI$_UNIT, unit = 0;
 
    if (!((status = lib$getdvi(&item_code, &chan, 0, &unit)) & 1))
        lib$stop(status);
    return unit;
 
 
short iosb[4];
 
/* Sub-process termination ast */
ast(int chan)
 
    /* Shut down the connection */
    if (!((status = sys$qiow(4, chan, IO$_DEACCESS|IO$M_SHUTDOWN, iosb,
                        0, 0, 0, 0, 0, UCX$C_DSC_ALL, 0, 0)) & 1))
        status = iosb[0];
    if (!(status & 1))
    {
        printf("AST: Failed to close socket on channel\n");;
        lib$stop(status);
    }
 
    /* Close the connection */
    if (!((status = sys$qiow(4, chan, IO$_DEACCESS, iosb,
                        0, 0, 0, 0, 0, 0, 0, 0)) & 1))
        status = iosb[0];
    if (!(status & 1))
    {
        printf("AST: Failed to close socket on channel\n");;
        lib$stop(status);
    }
 
    /* Deassign the UCX device channel. */
    if (!((status = sys$dassgn(chan)) & 1))
        printf("AST: Failed to deassign the channel.\n");
 
 
main(unsigned int argc, char *argv[])
 
    int r_retlen, one = 1; unsigned long pid, flags;
    short channel, channel_1, mbx_chan, sck_parm[2];
    char buf[512], bg_device[512]; unsigned char *dummy;
    struct SOCKADDRIN local_host, remote_host;
 
    struct IL2 { unsigned short il2_length, parameter_name; char *il2_address;
        } lhst_adrs = {sizeof local_host, INET$C_SOCK_NAME, 0};
 
    struct IL3 { unsigned short il3_length, parameter_name; char *il3_address;
                unsigned int il3_retlen;
        } rhst_adrs = {sizeof remote_host, INET$C_SOCK_NAME, 0, 0};
 
    $DESCRIPTOR(inet_dev, "UCX$DEVICE"); $DESCRIPTOR(mbx_name, "MY_MAILBOX");
    $DESCRIPTOR(timbuf, "0 :1:00"); $DESCRIPTOR(command, "run serverc_qio2");
    struct { short len, param; int *ptr; }
        item_list[] = {
                        {sizeof(one), UCX$C_SHARE, 0}
                      },
        options = {sizeof(item_list), UCX$C_SOCKOPT, 0};
 
    lhst_adrs. il2_address = (char *) &local_host;
    rhst_adrs.il3_address = (char *) &remote_host;
    rhst_adrs.il3_retlen  = (unsigned int) &r_retlen;
    item_list[0].ptr = &one;
    options.ptr = (int *) item_list;
 
    sck_parm[0] = UCX$C_TCP;            /* TCP/IP protocol */
    sck_parm[1] = INET_PROTYP$C_STREAM; /* stream type of socket */
    local_host.SIN$W_FAMILY = UCX$C_AF_INET;    /* INET family */
    local_host.SIN$L_ADDR = UCX$C_INADDR_ANY;   /* Any address */
    local_host.SIN$W_PORT = htons(atoi(argv[1]));
 
    if (argc != 2)
    {
        printf("Syntax: server portnumber\n");
        exit(-1);
    }
 
    /* Create a mailbox for sending BG device name to sub-processes */
    if (!((status = sys$crembx (0, &mbx_chan, 0, 0, 0, 0, &mbx_name,
                        0)) & 1)) lib$stop(status);
 
    /* Assign channel to the UCX device. */
    if (!((status = sys$assign(&inet_dev, &channel, 0, 0)) & 1))
    {
        printf("Failed to assign channel to UCX device\n");;
        lib$stop(status);
    }
 
    /* Create the socket, set the SHARE option & bind. */
    if ((status = sys$qiow(3, channel, IO$_SETMODE, iosb, 0, 0,
                        &sck_parm, 0, &lhst_adrs, 5, &options, 0)) & 1)
        status = iosb[0];
    if (!(status & 1))
    {
        printf("Failed to create and bind socket\n");;
        lib$stop(status);
    }
 
    /* Set up timer ast - to exit application if server is inactive for
       some time
    */
    if (!((status = sys$bintim(&timbuf, timadr)) & 1))
        lib$stop(status);
    if (!((status = sys$setimr(0, timadr, timer_ast, timer_id, 0)) & 1))
        lib$stop(status);
 
    /* Accept connections and spawn sub-processes to service clients */
    while (1)
    {
        /* Assign channel for client connection */
        if (!((status = sys$assign(&inet_dev, &channel_1, 0, 0)) & 1))
        {
                printf("Failed to assign channel(_1)\n");;
                lib$stop(status);
        }
 
        /* Accept a connection from a client. */
        if ((status = sys$qiow(3, channel, IO$_ACCESS|IO$M_ACCEPT,
                        iosb, 0, 0, 0, 0, &rhst_adrs, &channel_1, 0, 0)) & 1)
        status = iosb[0];
        if (!(status & 1))
        {
            printf("Failed to accept connection from client\n");;
            lib$stop(status);
        }
 
        reset_timer = TRUE;
        dummy = (unsigned char *) &remote_host.SIN$L_ADDR;
        printf("Connection from host: %d.%d.%d.%d, port: %d\n",
                dummy[0], dummy[1], dummy[2], dummy[3],
                htons(remote_host.SIN$W_PORT));
 
        /* Spawn a sub process to service this client. Set up a sub-process
           termination ast and pass connected channel number to this ast */
        flags = CLI$M_NOWAIT;
        if (!((status = lib$spawn (&command, 0, 0, &flags,
                            0, &pid, 0, 0, ast, channel_1, 0,
                            0,
                            0)) & 1))
            lib$stop(status);
 
        printf("Sub-process (pid = %x) is servicing this client\n", pid);
 
        /* Write the BG device name to the mailbox and wait for the spawned
           process to read it */
        sprintf(bg_device, "BG%d", ucx_bg_unit(channel_1));
        if ((status = sys$qiow(0, mbx_chan, IO$_WRITEVBLK, iosb, 0, 0,
                bg_device, strlen(bg_device), 0, 0, 0, 0)) & 1)
            status = iosb[0];
        if (!(status & 1))
        {
            printf("Parent: Failed to write to mailbox\n");;
            lib$stop(status);
        }
    }
     /* Close socket - listener */
    if (!((status = sys$qiow(3, channel, IO$_DEACCESS, iosb,
                        0, 0, 0, 0, 0, 0, 0, 0)) & 1))
        status = iosb[0];
    if (!(status & 1))
    {
        printf("Failed to close socket on channel\n");;
        lib$stop(status);
    }
 
    /* Deassign the UCX device channel. */
    if (!((status = sys$dassgn(channel)) & 1))
        printf("Failed to deassign the channel.\n");
 
-------------------------------
/* CHILD.C */
#include <in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <starlet.h>
#include <lib$routines.h>
#include <descrip.h>
#include <iodef.h>
#include <ucx$inetdef.h>        /* Provided during UCX installation */
 
main(unsigned int argc, char *argv[])
 
    register status; short channel, mbx_chan, iosb[4]; char dev[80], buf[80];
    $DESCRIPTOR(inet_dev, "UCX$DEVICE"); $DESCRIPTOR(mbx_name, "MY_MAILBOX");
 
    /* Assign a channel to an existing mailbox created by the parent */
    if (!((status = sys$crembx (0, &mbx_chan, 0, 0, 0, 0, &mbx_name, 0)) & 1))
        lib$stop(status);
 
    /* Read mailbox to get the BG device name */
    if ((status = sys$qiow(0, mbx_chan, IO$_READVBLK, iosb, 0, 0,
                        dev, sizeof(dev), 0, 0, 0, 0)) & 1)
        status = iosb[0];
    if (!(status & 1))
    {
        printf("Child: Error reading mailbox\n");
        lib$stop(status);
    }
 
    inet_dev.dsc$a_pointer = dev;
    inet_dev.dsc$w_length = strlen(dev);
    /* Assign channel to the UCX device. */
    if (!((status = sys$assign(&inet_dev, &channel, 0, 0)) & 1))
    {
        printf("Failed to assign channel to UCX device\n");;
        lib$stop(status);
    }
 
    while (1)
    {
            /* Read I/O buffer. */
            memset(buf, 0, sizeof buf);
            if ((status = sys$qiow(3, channel, IO$_READVBLK, iosb, 0, 0,
                        buf, sizeof buf, 0, 0, 0, 0)) & 1)
                status = iosb[0];
            if (!(status & 1))
            {
                printf("Failed to read message from client\n");;
                lib$stop(status);
            }
 
            buf[iosb[1]] = 0;
            if (strcmp(buf, "exit") == 0) break;
            printf ("%s\n", buf);
 
            /* Send message back to the client */
            strcat(buf, " RECEIVED BY SERVER");
            if ((status = sys$qiow(3, channel, IO$_WRITEVBLK, iosb, 0, 0,
                        buf, strlen(buf), 0, 0, 0, 0)) & 1)
                status = iosb[0];
            if (!(status & 1))
            {
                printf("Failed to send message to client\n");
                lib$stop(status);
            }
    }
 
    /* Deassign the UCX device channels. */
    if (!((status = sys$dassgn(channel)) & 1))
        printf("Failed to deassign the channel.\n");
 
 

answer written or last revised on ( 16-MAR-2000 )

» close window