HP OpenVMS Systemsask the wizard |
The Question is: Hello, i have a simple question. I searched into the FAQ and news groups but i didn't found anything. Where can i find an example in FORTRAN to exchange a string 'hello world' by TCPIP between a sender and a receiver program? That's all, thank you very much, Jan Lemmens The Answer is :
Example programs are generally available from the Compaq Customer
Support Center, as well as via the Compaq DSNlink service.
C and Macro32 examples are available in UCX$EXAMPLES on TCP/IP Services
versions prior to V5.0, and in TCPIP$EXAMPLES in V5.0 and later.
With Fortran, you will be using the sys$qio[w] interface.
An example follows:
PROGRAM ucx_tcp_server_qio_for2
C ** Modified version of ucx_tcp_server_qio_for.for
C which sits waiting for a client connection. When
C a cient connects, it waits for the client to send
C messages, and displays them. If the message is 'exit',
C this program finishes.
C ** If the client terminates, this sets a SS$_LINKDISCON
C status in the $QIOW IOSB. This program then deassigns
C the channel; assigns a new one and awaits for a new
C client to connect.
C This is a FORTRAN version of the TCP/IP Services for OpenVMS
C example program UCX$EXAMPLES:UCX$TCP_SERVER_QIO.C
C The best reference for SYS$QIO programming for socket usage is
C the "TCP/IP Services for OpenVMS: System Services and C Socket
C Programming" manual, chapter 3.
C To build:
C $ FORTRAN ucx_tcp_server_qio_for
C $ LINK ucx_tcp_server_qio_for
C To run:
C $ RUN ucx_tcp_server_qio_for
C Build and run a client program such as
C UCX$EXAMPLES:UCX$TCP_CLIENT_QIO.C, UCX$EXAMPLES:UCX$TCP_CLIENT_IPC.C
C or UCX_TCP_CLIENT_QIO_FOR.FOR which connects to the server and sends
C a message to the server. The server simply displays the message and
C then exits.
C John Wood Compaq Computer (UK) Ltd January 1999
IMPLICIT NONE
C ** include useful system definitions
INCLUDE '(lib$routines)'
INCLUDE '($syssrvnam)'
INCLUDE '($iodef)'
INCLUDE '($ssdef)'
INCLUDE 'sys$library:ucx$inetdef.for'
C ** declare variables
INTEGER*4 buflen
INTEGER*4 retval
INTEGER*4 status
INTEGER*4 r_retlen
INTEGER*4 one
INTEGER*4 a, b, c, d
INTEGER*4 flags
INTEGER*4 efn ! ** event flag number for SYS$QIO
INTEGER*2 port, port_1
INTEGER*2 channel, channel_1, channel_2
INTEGER*2 sck_parm(2)
INTEGER*4 client_addr
INTEGER*1 bytes(4)
EQUIVALENCE (client_addr, bytes)
C ** there are various ways to define the I/O status block:
CCC INTEGER*2 iosb(4)
STRUCTURE / iosb_struct /
INTEGER*2 status
INTEGER*2 transfer_size
INTEGER*4 address
END STRUCTURE
RECORD /iosb_struct/ iosb
CHARACTER*512 buf
RECORD / sockaddrin / local_host, remote_host
STRUCTURE / struct_il2 /
INTEGER*4 il2_length
INTEGER*4 il2_address ! address
END STRUCTURE
RECORD /struct_il2/ lhst_adrs
STRUCTURE / struct_il3 /
INTEGER*4 il3_length
INTEGER*4 il3_address ! address
INTEGER*4 il3_retlen ! address
END STRUCTURE
RECORD /struct_il3/ rhst_adrs
STRUCTURE / struct_ssp /
INTEGER*2 len
INTEGER*2 param
INTEGER*4 ptr ! address
END STRUCTURE
RECORD / struct_ssp / options, item_list(1)
C ** function declarations
INTEGER*2 htons
C *************************************************
buflen = SIZEOF( buf )
one = 1
C ** get an available event flag
status = lib$get_ef( efn ) ! efn by %REF by default
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
IF (efn .EQ. -1) CALL lib$stop( %VAL( 0 ) )
item_list(1).len = SIZEOF( one )
item_list(1).param = ucx$c_reuseaddr
item_list(1).ptr = %LOC( one )
options.len = SIZEOF( item_list )
options.param = ucx$c_sockopt
options.ptr = %LOC( item_list )
local_host.SIN$W_FAMILY = UCX$C_AF_INET ! INET family
local_host.SIN$L_ADDR = UCX$C_INADDR_ANY ! Any address
lhst_adrs.il2_length = SIZEOF( local_host )
lhst_adrs.il2_address = %LOC( local_host )
rhst_adrs.il3_length = SIZEOF( remote_host )
rhst_adrs.il3_address = %LOC( remote_host )
rhst_adrs.il3_retlen = %LOC( r_retlen )
C GOTO 110 ! ** for testing, use hard-coded port number
WRITE (6, *) ' Enter port number '
READ (5,*) port
GOTO 120
110 CONTINUE ! don't worry about compile-time warnings for this line
C ** for testing, skip prompting user for port
port = 4747
120 CONTINUE
local_host.sin$w_port = htons( port )
WRITE (6,*) 'Server will use port ', port
WRITE (6,*) 'Server port in network format = ',
& local_host.sin$w_port
C ----------------------------------------
C ** Assign two channels to the UCX device
C ** (These calls will fail if UCX is not started on the system...)
C ** the string 'ucx$device' is passed by descriptor by default
status = sys$assign( 'ucx$device', channel, , )
if (.not. status) call lib$stop( %val(status) )
status = sys$assign( 'ucx$device', channel_2, , )
if (.not. status) call lib$stop( %val(status) )
C -------------------------------------------------
C ** Create the socket and set the REUSEADDR option
sck_parm(1) = UCX$C_TCP ! TCP/IP protocol
sck_parm(2) = INET_PROTYP$C_STREAM ! stream type of socket
status = sys$qiow( %VAL( efn ),
& %VAL( channel ),
& %VAL( io$_setmode ),
& %REF( iosb ),
& ,
& ,
& %REF( sck_parm ), ! p1
& , ! p2
& , ! p3
& , ! p4
& options, ! p5
& ) ! p6
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
status = iosb.status
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
C ------------------------------------------------------------
C ** Bind to chosen port number (after REUSEADDR is set above)
status = sys$qiow( %VAL( efn ),
& %VAL( channel ),
& %VAL( io$_setmode ),
& %REF( iosb ),
& ,
& ,
& , ! p1
& , ! p2
& lhst_adrs, ! p3 : local socket name
& %VAL( 3 ), ! p4 : Connection backlog
& , ! p5
& ) ! p6
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
status = iosb.status
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
GOTO 222
C -----------------------------------------------
C ** If here, a client has closed the connection.
C ** So we de-assign the channel, ready to re-assign it below.
200 CONTINUE
status = sys$dassgn( %VAL(channel_1) )
IF (.NOT. status) call lib$stop( %VAL(status) )
TYPE *, 'Lost connection with client; awaiting new connection'
C ------------------------------------
C ** Accept a connection from a client
222 CONTINUE
status = sys$assign( 'ucx$device', channel_1, , )
IF (.NOT. status) CALL lib$stop( %VAL(status) )
status = sys$qiow( %VAL( efn ),
& %VAL( channel ),
& %VAL( io$_access .OR. io$m_accept ),
& %REF( iosb ),
& ,
& ,
& , ! p1
& , ! p2
& rhst_adrs, ! p3 : Remote IP address
& channel_1, ! p4 : Channel for new socket
& , ! p5
& ) ! p6
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
status = iosb.status
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
port_1 = htons( remote_host.sin$w_port )
C ** extract & display IP address from remote host
C ** copy client address into equivalenced datum
client_addr = remote_host.sin$l_addr
C ** rem: 16.37.144.139 = 0x10 0x25 0x90 0x8B
C ** in remote_host.sin$l_addr format, = 0x8B 90 25 10 = d.c.b.a
C ** rem: INTEGER*1 bytes(4) is equivalenced to client_addr
a = bytes(1)
b = bytes(2)
c = bytes(3)
d = bytes(4)
if (a .lt. 0) a = a + 256
if (b .lt. 0) b = b + 256
if (c .lt. 0) c = c + 256
if (d .lt. 0) d = d + 256
WRITE (6,601) client_addr, a, b, c, d, port_1
601 FORMAT ( ' Connection from client (', I, '): ', I3, '.',
& I3, '.', I3, '.', I3, '; port ', I5 )
C ------------------
C ** Read I/O buffer
300 continue
status = sys$qiow( %VAL( efn ),
& %VAL( channel_1 ),
& %VAL( io$_readvblk ),
& %REF( iosb ),
& ,
& ,
& %REF( buf ), ! p1 : buffer
& %VAL( buflen ), ! p2 : buffer length
& , ! p3
& , ! p4
& , ! p5
& ) ! p6
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
status = iosb.status
C ** check that client hasn't closed the connection; if so, go to 200
IF (status .eq. SS$_LINKDISCON) goto 200
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
C ** If all is well, print message (all 512 bytes!)
TYPE *, 'Received ', iosb.transfer_size, ' bytes; text: ', buf
IF (buf .EQ. 'exit') GOTO 400
goto 300
C ----------------------------------
C ** Shut down the socket (optional)
400 continue
status = sys$qiow( %VAL( efn ),
& %VAL( channel_1 ),
& %VAL( io$_deaccess .or. io$m_shutdown ),
& %REF( iosb ),
& ,
& ,
& , ! p1
& , ! p2
& , ! p3
& , ! p4
& , ! p5
& ) ! p6
IF (.NOT. status) CALL lib$stop( %val(status) )
status = iosb.status
IF (.NOT. status) CALL lib$stop( %val(status) )
C -------------------------------------------------------
C ** Close the sockets -- accepted and listner (optional)
status = sys$qiow( %VAL( efn ),
& %VAL( channel_1 ),
& %VAL( io$_deaccess ),
& %REF( iosb ),
& ,
& ,
& , ! p1
& , ! p2
& , ! p3
& , ! p4
& , ! p5
& ) ! p6
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
status = iosb.status
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
status = sys$qiow( %VAL( efn ),
& %VAL( channel ),
& %VAL( io$_deaccess ),
& %REF( iosb ),
& ,
& ,
& , ! p1
& , ! p2
& , ! p3
& , ! p4
& , ! p5
& ) ! p6
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
status = iosb.status
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
C -------------------------------------------------------
C ** Deassign the UCX device channels
status = sys$dassgn( %VAL( channel_1 ) )
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
status = sys$dassgn( %VAL( channel ) )
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
C ** free the event flag
status = lib$free_ef( efn ) ! passed by %REF by default
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
C -------------------------------------------------------
C ** Inform user that program ran to completion:
C ** if you don't see the following msg, then run the program
C ** under the debugger to see where it calls lib$stop()
PRINT *, 'All is well that ends well'
END
C -----------------
INTEGER*2 FUNCTION htons( port )
INTEGER*2 port
INTEGER*2 high, low
C ** swap the two bytes of 'port' around
low = IMOD( port, 256 )
high = port / 256
htons = (256*low) + high
END
--------------------------------------------------------------------------------
PROGRAM ucx_tcp_client_qio_for2
C ** Modified version of ucx_tcp_client_qio_for.for
C which makes a socket connection to a server. It
C prompts the user to enter a message which it sends
C to the server. If the message is 'exit', the client
C sends 'exit' to the server and then finishes. If the
C message is 'quit', no message is sent to the server:
C this program just finishes.
C ** After sending any message other than 'exit', this program
C loops; prompting the user for another message to be sent.
C This is a FORTRAN version of the TCP/IP Services for OpenVMS
C example program UCX$EXAMPLES:UCX$TCP_CLIENT_QIO.C
C The best reference for SYS$QIO programming for socket usage is
C the "TCP/IP Services for OpenVMS: System Services and C Socket
C Programming" manual, chapter 3.
C To build:
C $ FORTRAN ucx_tcp_client_qio_for
C $ LINK ucx_tcp_client_qio_for
C To run, first build & run ones of the following server programs:
C UCX$EXAMPLES:UCX$TCP_SERVER_QIO.C
C UCX$EXAMPLES:UCX$TCP_SERVER_IPC.C
C UCX_TCP_SERVER_QIO_FOR.FOR
C Then run this program to connect to the server:
C $ RUN ucx_tcp_client_qio_for
C This client sends a simple message ('hello there') to the server.
C John Wood Compaq Computer (UK) Ltd January 1999
IMPLICIT NONE
C ** include useful system definitions
INCLUDE '(lib$routines)'
INCLUDE '($syssrvnam)'
INCLUDE '($iodef)'
INCLUDE 'sys$library:ucx$inetdef.for'
C ** declare variables
INTEGER*4 buflen
INTEGER*4 status
INTEGER*4 a, b, c, d, e
INTEGER*4 flags
INTEGER*4 efn ! ** event flag number for SYS$QIO
INTEGER*2 port
INTEGER*2 channel
INTEGER*2 sck_parm(2)
C ** there are various ways to define the I/O status block:
C ** you could declare a structure, but this program treats
C ** it as an array of 16-bit values
INTEGER*2 iosb(4)
CHARACTER*512 buf / 'Hello There' /
RECORD / sockaddrin / remote_host
STRUCTURE / struct_il2 /
INTEGER*4 il2_length
INTEGER*4 il2_address ! address
END STRUCTURE
RECORD /struct_il2/ rhst_adrs
C ** function declarations
INTEGER*2 htons
C ---------------------------------------------------------------
buflen = sizeof( buf )
C ** get an available event flag
status = lib$get_ef( efn )
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
IF (efn .EQ. -1) CALL lib$stop( %VAL( 0 ) )
rhst_adrs.il2_length = sizeof( remote_host )
rhst_adrs.il2_address = %LOC( remote_host )
sck_parm(1) = UCX$C_TCP ! TCP/IP protocol
sck_parm(2) = INET_PROTYP$C_STREAM ! stream type of socket
remote_host.SIN$W_FAMILY = UCX$C_AF_INET ! INET family
C GOTO 110 ! skip prompting user for IP server details during testing
TYPE *, 'Enter IP address and port number for server:'
TYPE *, 'use comma "," not . to separate IP address parts'
TYPE *, 'E.g. "16,37,144,139, 4747" for 16.37.144.139 4747'
READ (5,501) a, b, c, d, port
501 FORMAT( I, I, I, I, I )
GOTO 120
110 CONTINUE ! can ignore compile-time warnings about this line
C ** hard-code IP address of server host during testing (a.b.c.d)
a = 16
b = 37
c = 144
d = 139
port = 4747
120 CONTINUE
PRINT *, 'Server address = ', a, '.', b, '.', c, '.', d
PRINT *, 'Server port = ', port
C ** sin$l_adr needs to store an IP address of form a.b.c.d
C ** in the byte order d:c:b:a
remote_host.sin$l_addr = (d * 256 * 256 * 256) +
& (c * 256 * 256) +
& (b * 256) +
& (a)
remote_host.sin$w_port = htons( port )
PRINT *, 'Server host address as an integer = ',
& remote_host.sin$l_addr
PRINT *, 'Server port in network format = ',
& remote_host.sin$w_port
C -------------------------------------
C ** assign a channel to the UCX device
print *, 'Assigning a channel to the UCX device'
C ** the string 'ucx$device' is passed by descriptor by default
status = sys$assign( 'ucx$device', channel, , )
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
C --------------------
C ** Create the socket
PRINT *, 'Creating the socket'
status = sys$qiow( %VAL( efn ), ! Event flag
& %VAL( channel ), ! Channel number
& %VAL( IO$_SETMODE ), ! I/O function
& %REF( iosb ), ! I/O status block
& , ! AST rtn address
& , ! AST parameter
& %REF( sck_parm ), ! p1 : Socket creation parameter
& , ! p2
& , ! p3
& , ! p4
& , ! p5
& ) ! p6
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
status = iosb(1)
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
C --------------------------------------------
C ** Connect to specified host and port number
PRINT *, 'Connecting to specified host and port number'
status = sys$qiow( %VAL( efn ), ! Event flag
& %VAL( channel ), ! Channel number
& %VAL( IO$_ACCESS ), ! I/O function
& %REF( iosb ), ! I/O status block
& , ! AST rtn address
& , ! AST parameter
& , ! p1
& , ! p2
& %REF( rhst_adrs ), ! p3 : remote IP address
& , ! p4
& , ! p5
& ) ! p6
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
status = iosb(1)
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
C --------------------------------
C ** Get message to send to server
300 CONTINUE
TYPE *, 'Enter message to send to server'
TYPE *, '(or ''exit'' or ''quit'')'
READ (5,511) buf
511 FORMAT( A )
IF (buf .EQ. 'quit') GOTO 400
C -------------------
C ** Write I/O buffer
PRINT *, 'Writing I/O buffer ', buf
status = sys$qiow( %VAL( efn ), ! Event flag
& %VAL( channel ), ! Channel number
& %VAL( IO$_WRITEVBLK ), ! I/O function
& %REF( iosb ), ! I/O status block
& , ! AST rtn address
& , ! AST parameter
& %REF( buf ), ! p1 : buffer address
& %VAL( buflen ), ! p2 : buffer length
& , ! p3
& , ! p4
& , ! p5
& ) ! p6
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
status = iosb(1)
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
IF (buf .EQ. 'exit') GOTO 400
GOTO 300
C ----------------------------------
C ** Shut down the socket (optional)
400 continue
flags = io$_deaccess .OR. io$m_shutdown
PRINT *, 'Shutting down the socket'
status = sys$qiow( %VAL( efn ), ! Event flag
& %VAL( channel ), ! Channel number
& %VAL( flags ), ! I/O function
& %REF( iosb ), ! I/O status block
& , ! AST rtn address
& , ! AST parameter
& , ! p1
& , ! p2
& , ! p3
& %VAL( ucx$c_dsc_all ), ! p4 : Discard all packets
& , ! p5
& ) ! p6
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
status = iosb(1)
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
C ------------------------------
C ** Close the socket (optional)
PRINT *, 'Closing the socket'
status = sys$qiow( %VAL( efn ), ! Event flag
& %VAL( channel ), ! Channel number
& %VAL( IO$_DEACCESS ), ! I/O function
& %REF( iosb ), ! I/O status block
& , ! AST rtn address
& , ! AST parameter
& , ! p1
& , ! p2
& , ! p3
& , ! p4
& , ! p5
& ) ! p6
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
status = iosb(1)
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
C ----------------------------------
C ** Deassign the UCX device channel
print *, 'Deassigning the UCX device channel'
status = sys$dassgn( %VAL( channel ) )
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
C ** free the event flag
status = lib$free_ef( %REF( efn ) )
IF (.NOT. status) CALL lib$stop( %VAL( status ) )
C -------------------------------------------------------
C ** Inform user that program ran to completion:
C ** if you don't see the following msg, then run the program
C ** under the debugger to see where it calls lib$stop()
PRINT *, 'All is well that ends well'
END
C --------------------------------------------------------------------------
INTEGER*2 FUNCTION htons( port )
INTEGER*2 port
INTEGER*2 high, low
C ** swap the two bytes of 'port' around
low = IMOD( port, 256 )
high = port / 256
htons = (256*low) + high
END
|