![]() |
![]() HP OpenVMS Systemsask the wizard |
![]() |
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");
|