Previous Topic: Assembler ExamplesNext Topic: Assembler TCP/IP Generic Listener Server Program


Assembler TCP/IP Client Program

TITLE 'Sample ASSEMBLER client TCP/IP program'
* ASMCLI   RENT EP=ASMCLIEP
******************************************************************
* The following program is an example of a TCP/IP client         *
* client program written in Assembler.                           *
* The processing is the following:                               *
*  - Create a socket for the client program.                     *
*  - Convert the known dotted string format IPA to binary.       *
*  -   (Host IPA is defined in IPADOT, see below.)               *
*  - Find host information for connection.                       *
*  -   (Host port is defined in DESTPORT, see below.)            *
*  - Establish a connection to the host listener.                *
*  - Send message 1 to the listener (first 4 bytes = data length)*
*  - Read message 1 from  listener (first 4 bytes = data length) *
*  - Send message 2 to the listener (first 4 bytes = data length)*
*  - Read message 2 from  listener (first 4 bytes = data length) *
*  - Close socket and exit.                                      *
******************************************************************
*---------------------------------------------------------------------*
         MACRO
&LABEL.   #SAVEREG
&LABEL.   ST    R12,0(,R13)         Save R12
         ST    R14,4(,R13)         Save R14
         STM   R2,R8,8(R13)        Save R2-R8
         LA    R13,9*4(,R13)
         MEND
*---------------------------------------------------------------------*
         MACRO
&LABEL.   #RESTREG
&LABEL.   LA    R12,9*4             Get register stack entry length
         SR    R13,R12             Get A(previous register stack entry)
         L     R12,0(,R13)         Restore R12
         L     R14,4(,R13)         Restore R14
         LM    R2,R8,8(R13)        Restore R2-R8
         MEND
*---------------------------------------------------------------------*
         MACRO
&LABEL.   MSGTXT &TXT.
         LCLC  &TMP.
&TMP.     SETC  '&SYSNDX'.
&LABEL.   DC    AL1(L2&TMP).
L1&TMP.   DC    C&TXT.
L2&TMP.   EQU   *-L1&TMP.
         MEND
*---------------------------------------------------------------------*
ASMCLI   CSECT
         @MODE MODE=IDMSDC
         #MOPT CSECT=ASMCLI,ENV=USER,RMODE=ANY,AMODE=ANY
         ENTRY ASMCLIEP
ASMCLIEP DS    0H
         BALR  R12,0
         BCTR  R12,0
         BCTR  R12,0
         USING ASMCLIEP,R12
         B     TCPSTART            Branch around constants
*---------------------------------------------------------------------*
* Modify the following connection parameters before compiling        -*
*---------------------------------------------------------------------*
         DS    0F
DESTPORT DC    F'12345'             Known host port for connection
IPADOT   DC    CL13'255.255.00.01'  Known IP address of host
         DC    CL4'   '             filler
IPADOTL  DC    F'17'                Total length of dotted string IPA
MAX_LOOP DC    F'2'                 Maximum message count to send
*
TCPSTART DS    0H
*
         #GETSTG TYPE=(USER,SHORT),ADDR=(R1),PLIST=*,INIT=X'0',        X
               LEN=WORKAREL
         LR    R11,R1
         USING WORKAREA,R11
         LA    R13,REGSTACK          R13 -> Register stack
*  Initialize some WORKAREA fields
         XR    R5,R5
         ST    R5,ERRCOUNT
         MVI   OUTAREA,L'OUTAREAT
         MVC   OVRLOG,=X'8000000000'
         MVC   OVRLOGCO,=X'C000000000'
         MVC   WKCLEAR,=XL8'0F0F0F0F0F0F0F0F'
         MVC   TRTAB,=CL16'0123456789ABCDEF'
         MVC   TRTABX,=XL6'FAFBFCFDFEFF'
******************************************************************
* Create a socket in the communications domain                   *
******************************************************************
         LA    R1,MSG01            Display socket function.
         L     R15,=A(DISLINE)
         BALR  R14,R15
         #SOCKET SOCKET,                                               X
               DOMAIN=AF@INET,                                         X
               TYPE=STREAM,                                            X
               PROTNUM=6,                                              X
               NEWSOCK=S_NEWSOC,                                       X
               RETCODE=RETCODE,ERRNO=ERRNO,RSNCODE=RSNCODE
         LA    R1,MSG02            Display results of socket function.
         L     R15,=A(DISRC)
         BALR  R14,R15             Display the 3 return codes.
         CLC   RETCODE,=F'0'       Socket function successful?
         BNE   TCPCLOSE             N. Close socket and exit.
******************************************************************
* Convert the IP address from dotted string format to binary.    *
******************************************************************
         LA    R1,MSG12            Display INET_PTON socket function.
         L     R15,=A(DISLINE)
         BALR  R14,R15
         #SOCKET INET_PTON,DOMAIN=AF@INET,                             X
               IPADDRS=IPADOT,IPADDRSL=IPADOTL,IPADDR=HOSTIPA,         X
               RETCODE=RETCODE,ERRNO=ERRNO,RSNCODE=RSNCODE
         LA    R1,MSG13            Display INET_PTON results.
         L     R15,=A(DISRC)
         BALR  R14,R15             Display the 3 return codes.
******************************************************************
* Take the IP address and domain and resolve it through a name   *
* server. If successful, return the information in a HOSTENT     *
* structure.                                                     *
******************************************************************
         LA    R1,MSG14             Display GETHOSTBYADDR function.
         L     R15,=A(DISLINE)
         BALR  R14,R15
         LA    R2,BUFFER            R2 -> buffer for host information
         #SOCKET GETHOSTBYADDR,IPADDR=HOSTIPA,IPADDRL=4,               X
               DOMAIN=AF@INET,HOSTENTP=(R2),                           X
               RETCODE=RETCODE,ERRNO=ERRNO,RSNCODE=RSNCODE
         LA    R1,MSG15            Display GETHOSTBYADDR results
         L     R15,=A(DISRC)
         BALR  R14,R15             Display the 3 return codes
         CLC   RETCODE,=F'0'       GETHOSTBYADDR successful?
         BNE   TCPCLOSE             N. Close socket and exit.
******************************************************************
* Prepare to connect to DESTPORT                                 *
******************************************************************
         LA    R5,SOCKADDC          R5 -> Socket address structure.
         USING SOCK@IN,R5
         MVI   SIN@FAM,AF@INET       Get the family,
         MVC   SIN@ADDR(4),HOSTIPA         binary IPA, and
         MVC   SIN@PORT(2),DESTPORT+2       port number
         LA    R1,MSG03                       for the Host connect.
         L     R15,=A(DISLINE)       Display socket connect function.
         BALR  R14,R15
******************************************************************
* Connect to DESTPORT                                            *
******************************************************************
         #SOCKET CONNECT,                                              X
               SOCK=S_NEWSOC,                                          X
               SOCKADDR=(R5),                                          X
               SOCKADDL=SIN#LEN,                                       X
               RETCODE=RETCODE,ERRNO=ERRNO,RSNCODE=RSNCODE
         LA    R1,MSG04
         L     R15,=A(DISRC)
         BALR  R14,R15             Display the 3 return codes.
         CLC   RETCODE,=F'0'       Connect successful?
         BNE   TCPCLOSE             N. Close socket and exit.
******************************************************************
* Write and read two messages to/from DESTPORT                   *
******************************************************************
WRLOOP   DS    0H
         L     R5,LOOP_CNT              Add 1
         LA    R5,1(R5)                    to current
         ST    R5,LOOP_CNT                     message count
         ST    R5,WORK1                             and
         UNPK  WORK2(9),WORK1(5)                      make
         NC    WORK2(8),WKCLEAR                        it
         TR    WORK2(8),TRTAB                     displayable.
         MVC   BUFTXT_S(1),WORK2+7
         LA    R7,BUFFER_A              R7 -> buffer array.
*                                       Build client message.
******************************************************************
* Send a message to the listener                                 *
******************************************************************
         MVC   BUFTXT_M(33),=C'ASMCLI TCP/IP test message number'
         MVC   BUFTXT_B(1),=C' '        Blank character.
         MVC   BUFLEN(4),=F'43'         Length of message text.
         MVC   WK_LEN(4),=F'47'         Total length of message.
         BAL   R4,TCPWRITE              Send message to listener.
*
******************************************************************
* Read the first 4 bytes of reply: contains the remaining length *
******************************************************************
         LA    R5,4
         ST    R5,WK_LEN
         XR    R5,R5
         ST    R5,BUFLEN
         LA    R7,BUFFER_A              R7 -> buffer array.
         BAL   R4,TCPREAD               Perform socket read function.
*
         CLC   BUFLEN(4),=F'80'          Incoming buffer less than 80?
         BL    READLIS                    Y. Read listener reply.
         LA    R1,MSG11                   N. Reply too long,issue
         L     R15,=A(DISLINE)               error message
         BALR  R14,R15                     and
         B     TCPCLOSE                  close socket.
READLIS  DS    0H
         MVC   WK_LEN,BUFLEN              Reply msg length=read length.
         LA    R7,BUFFER_A+4              R7 -> reply from listener.
         BAL   R4,TCPREAD                 Read listener reply.
*
         CLC   MAX_LOOP,LOOP_CNT          All messages sent?
         BH    WRLOOP                      N. loop until done.
         B     TCPCLOSE                    Y. Close socket and exit.
******************************************************************
* Routine to read a message from DESTPORT                        *
******************************************************************
TCPREAD  DS    0H
         LA    R1,MSG05                   Display socket read function.
         L     R15,=A(DISLINE)
         BALR  R14,R15
        #SOCKET  READ,SOCK=S_NEWSOC,BUFFER=(R7),                       X
               RETLEN=RETLEN,BUFFERL=WK_LEN,                           X
               RETCODE=RETCODE,ERRNO=ERRNO,RSNCODE=RSNCODE
*
         LA    R1,MSG06      Display results of read.
         L     R15,=A(DISRC)
         BALR  R14,R15       Display the 3 return codes.codes
         CLC   RETCODE,=F'0' Successful read?
         BNE   TCPCLOSE        N.  Error close socket.
         A     R7,RETLEN     Adjust buffer array pointer
         L     R5,WK_LEN        and
         S     R5,RETLEN         read length
         ST    R5,WK_LEN        with reply length.
         CLI   WK_LEN,0        Read done?
         BNE   TCPREAD          N. Read some remainder.
         BR    R4               Y. Return.
******************************************************************
* Routine to send a message to DESTPORT                          *
******************************************************************
TCPWRITE DS    0H               Display socket write function.
         LA    R1,MSG07
         L     R15,=A(DISLINE)
         BALR  R14,R15
        #SOCKET WRITE,SOCK=S_NEWSOC,BUFFER=(R7),                       X
               RETLEN=RETLEN,BUFFERL=WK_LEN,                           X
               RETCODE=RETCODE,ERRNO=ERRNO,RSNCODE=RSNCODE
*
         LA    R1,MSG08                Display results of socket write.
         L     R15,=A(DISRC)
         BALR  R14,R15                 Display the 3 return codes.
*
         CLC   RETCODE,=F'0'           Write successful?
         BNE   TCPCLOSE                  N. Close socket and exit.
         MVC   OUTAREA,WK_LEN+3        Message text length.
         MVC   OUTAREAT,BUFTXT80       Message text.
         LA    R1,OUTAREA              Display buffer contents
         L     R15,=A(DISLINE)
         BALR  R14,R15
*
         A     R7,RETLEN                Adjust buffer array
         L     R5,WK_LEN                  and
         S     R5,RETLEN                   write length
         ST    R5,WK_LEN                    with message length.
         CLI   WK_LEN,0                 Anything left to write?
         BNE   TCPWRITE                   Y. Loop back.
         BR    R4                         N. Return.
******************************************************************
* Close the socket and exit                                      *
******************************************************************
TCPCLOSE DS    0H
         LA    R1,MSG09            Display closing socket.
         L     R15,=A(DISLINE)
         BALR  R14,R15             Display the 3 return codes.
         #SOCKET CLOSE,SOCK=S_NEWSOC,                                  X
               RETCODE=RETCODE,ERRNO=ERRNO,RSNCODE=RSNCODE
*
         LA    R1,MSG10            Display socket close function.
         L     R15,=A(DISRC)
         BALR  R14,R15             Display the 3 return codes.
*
         MVC   OUTAREAT(41),MSG99+1  Display ASMCLI temrimation msg.
         L     R5,ERRCOUNT           Get number of socket errors
         ST    R5,WORK1                 and
         UNPK  WORK2(9),WORK1(5)           make
         NC    WORK2(8),WKCLEAR               it
         TR    WORK2(8),TRTAB                  displayable
         MVC   ERRINDEC(4),WORK2+4                on the
         MVC   OUTAREAT+41(4),ERRINDEC             terminal.
         IC    R3,MSG99
         LA    R3,4(R3)
         STC   R3,OUTAREA
         LR    R1,R3
         LA    R3,OUTAREAT
         #LINEOUT OUTLEN=(R1),OUTAREA=(R3),OPTNS=(NOWAIT,TRLATIN)
*
         LA    R3,OUTAREA
         #WTL  MSGID=M#999043,MSGDICT=NO,OVRIDES=OVRLOG,               X
               PARMS=((R3)),RGSV=(R2-R8)
*
         #RETURN
         #BALI
*
         DROP  R12
         LTORG
         TITLE 'ASMCLI   - DISRC : DISPLAY THE RETURN CODES'
*---------------------------------------------------------------------*
*-  Routine to display the 3 return values from any TCP/IP calls.    -*
*-  Input : RETCODE, ERRNO and RSNCODE from the WORKAREA             -*
*-          R1 -> String to start with (e.g. MSGTXT format)          -*
*---------------------------------------------------------------------*
DISRC    DS    0H
         #SAVEREG                  Save the caller's registers
*
         LR    R12,R15
         USING DISRC,R12
*
         MVI   OUTAREA,L'OUTAREAT
         MVI   OUTAREAT,C' '
         MVC   OUTAREAT+1(L'OUTAREAT-1),OUTAREAT
*
         XR    R2,R2
         IC    R2,0(,R1)               Get message length
         BCTR  R2,0                    -1 for EX
         EX    R2,DISRCEX              Copy text
         LA    R2,1+1+OUTAREAT(R2)     Point to next free space
*
         CLC   RETCODE,=F'0'
         BE    DISRC00
         L     R3,ERRCOUNT
         LA    R3,1(R3)
         ST    R3,ERRCOUNT
DISRC00  DS    0H
         MVC   WORK1(4),RETCODE
         UNPK  WORK2(9),WORK1(5)
         NC    WORK2(8),WKCLEAR
         TR    WORK2(8),TRTAB
         MVC   0(8,R2),=CL8'RETCODE='
         MVC   8(8,R2),WORK2
*
         L     R15,ERRNO
         CVD   R15,WORK1
         OI    WORK1+7,X'0F'
         UNPK  WORK2(10),WORK1+2(6)
         LA    R14,WORK2
         LA    R15,9
DISRC01  DS    0H
         CLI   0(R14),C'0'
         BNE   DISRC02
         MVI   0(R14),C' '
         LA    R14,1(,R14)
         BCT   R15,DISRC01
DISRC02  DS    0H
         MVC   17(8,R2),=CL6'ERRNO='
         MVC   23(8,R2),WORK2+2
*
         MVC   WORK1(4),RSNCODE
         UNPK  WORK2(9),WORK1(5)
         NC    WORK2(8),WKCLEAR
         TR    WORK2(8),TRTAB
         MVC   32(8,R2),=CL8'RSNCODE='
         MVC   40(8,R2),WORK2
*
         LA    R1,OUTAREA
         L     R15,=A(DISLINE)
         BALR  R14,R15
*
         #RESTREG                  Restore the caller's registers
         BR     R14
*
         DROP  R12
*
DISRCEX  MVC   OUTAREAT(0),1(R1)       COPY TEXT
         LTORG
         TITLE 'ASMCLI - DISLINE : Write message line to log'
*---------------------------------------------------------------------*
*-  Subroutine to write a message line to the log.                   -*
*-  Input : R1 = A(output message) (first byte = message length)     -*
*---------------------------------------------------------------------
DISLINE  DS    0H
         #SAVEREG                  Save the caller's registers
*
         LR    R12,R15
         USING DISLINE,R12
         LR    R3,R1                   Get parm in R3
*
         #WTL  MSGID=M#999043,MSGDICT=NO,OVRIDES=OVRLOG,               X
               PARMS=((R3)),RGSV=(R2-R8)
*
         #RESTREG                  Restore the caller's registers
*
         BR    R14
*
         DROP  R12
*
M#999043 DC  PL4'9990430'
*
MSG01    MSGTXT 'Creating Socket.'
MSG02    MSGTXT 'SOCKET call:'
MSG03    MSGTXT 'Connecting: '
MSG04    MSGTXT 'CONNECT call:'
MSG05    MSGTXT 'Starting read.'
MSG06    MSGTXT 'READ call:'
MSG07    MSGTXT 'Starting write.'
MSG08    MSGTXT 'WRITE call:'
MSG09    MSGTXT 'Closing Socket.'
MSG10    MSGTXT 'CLOSE call:'
MSG11    MSGTXT 'Data length too long.'
MSG12    MSGTXT 'Calling INET_PTON.'
MSG13    MSGTXT 'INET_PTON call:'
MSG14    MSGTXT 'Calling GETHOSTBYADDR.'
MSG15    MSGTXT 'GETHOSTBYADDR call:'
MSG99    MSGTXT 'Program ASMCLI terminated. Error count = '
*
         LTORG
*
*
         TITLE 'ASMCLI - WORK AREA'
WORKAREA DSECT
*----------------------------------*
*-  DYNAMIC DATA                  -*
*----------------------------------*
SYSPLIST DS    16F
REGSTACK DS    32F
*
         DS    0D
WORK1    DC    XL10'00'
         DS    0D
WORK2    DC    XL10'00'            AT LEAST 10 BYTES DOUBLEWORD ALIGNED
*
*
HOSTIPA  DS    F            Binary IPA address of host
HOSTENTP DS    F            Pointer to HOSTENT structure
LOOP_CNT DS    F            Message counter
WK_LEN   DS    F            Length for read or write
ERRCOUNT DS    F            Number of socket errors
ERRINDEC DS    CL4          Number of socket errors decimal
*
*
SOCKADDC DS    (SIN#LEN)X          SOCKADDR for the client
SOCKDESN DS    F
S_NEWSOC DS    F
RETLEN   DS    F
RETCODE  DS    F
ERRNO    DS    F
RSNCODE  DS    F
*
*
OUTAREA  DS    X
OUTAREAT DC    CL80' '             OUTPUT AREA
         DS    0F
BUFFER   DS    CL84
         ORG   BUFFER
BUFLEN   DS    F
BUFTXT80 DS    CL80
         ORG   BUFTXT80
BUFTXT_M DS    CL33                 Message text
BUFTXT_B DS    CL1                  Blank character
BUFTXT_S DS    CL5                  Message sequence number
BUFTXT_F DS    CL41                 Filler
         ORG   BUFFER
BUFFER_A DS    CL84
*
*
*
*----------------------------------*
*-  STATIC DATA                   -*
*----------------------------------*
*
OVRLOG   DS    X'8000000000'       #WTL TO LOG ONLY
OVRLOGCO DS    X'C000000000'       #WTL TO LOG + CONSOLE
*
*
WKCLEAR  DS    XL8'0F0F0F0F0F0F0F0F'
TRTAB    DS    CL16'0123456789ABCDEF'
TRTABX   DS    XL6'FAFBFCFDFEFF'
*
WORKAREL EQU   *-WORKAREA
*
*---------------------------------------------------------------------*
*-  TCP/IP TABLES                                                    -*
*---------------------------------------------------------------------*
*
         #SOCKET TCPIPDEF
         #SOCKET ERRNOS
*
         END   ASMCLIEP