midrange.com code scratchpad
Name:
Simple non blocking socket
Scriptlanguage:
Plain Text
Tabwidth:
4
Date:
02/20/2019 08:09:40 pm
IP:
Logged
Description:
Simple example of a non blocking socket. If I start a simple server on my linux box with:
netcat -l 56167
and then call the program I get TESTING 123 on my linux terminal. If the listener isn't running, the program immediately exits.
Code:
  1.       *  ‰ Must be compiled with ACTGRP of QILE and BINDDIR of QC2LE €
  2.      Hdftactgrp(*no) ACTGRP('QILE') BNDDIR('QC2LE')
  3.       *
  4.       *   Necessary procedrure prototypes with data definitions
  5.       *
  6.       *-- Socket address information structure ------------------------
  7.       *
  8.       *
  9.      D SocketAddr      DS
  10.      D   SinFamily                    5I 0
  11.      D   SinPort                      5U 0
  12.      D   SinAddr                     10U 0
  13.      D   SinZero                      8A   Inz( *ALLX'00' )
  14.       *
  15.       *
  16.       *
  17.       *-- I/O options (Fcntl) -----------------------------------------
  18.       *
  19.      D F_SETFL         S             10I 0 Inz(7)
  20.      D O_NONBLOCK      S             10I 0 Inz(128)
  21.       *
  22.      D EWOULDBLCK      C                   3406
  23.       *
  24.       *
  25.       *-- Error number information ------------------------------------
  26.       *
  27.      D ErrNo           S             10I 0 Based(ErrNo@)
  28.      D ErrNo@          S               *   Inz
  29.      D ErrMsg@         S               *   Inz
  30.       *
  31.       *
  32.       *-- Address families --------------------------------------------
  33.       *
  34.      D AF_UNIX         C                   1
  35.      D AF_INET         C                   2
  36.      D AF_NS           C                   6
  37.      D AF_TELEPH       C                   99
  38.       *
  39.       *
  40.       *-- Socket types ------------------------------------------------
  41.       *
  42.      D SOCK_STR        C                   1
  43.      D SOCK_DGRAM      C                   2
  44.      D SOCK_RAW        C                   3
  45.      D SOCK_SEQ        C                   5
  46.       *
  47.      D SOL_SOCKET      C                   -1
  48.       *
  49.       *
  50.       *-- Socket level options ----------------------------------------
  51.       *
  52.      D SO_BROAD        C                   5
  53.      D SO_DEBUG        C                   10
  54.      D SO_DONTRT       C                   15
  55.      D SO_ERROR        C                   20
  56.      D SO_KEEPAL       C                   25
  57.      D SO_LINGER       C                   30
  58.       *
  59.      D SO_REUSEAD      C                   55
  60.       *
  61.       *
  62.       *-- Internet address specifications -----------------------------
  63.       *
  64.      D INADDR_ANY      C                   0
  65.      D INADDR_BR       C                   -1
  66.      D INADDR_LB       C                   X'7F000000'
  67.      D INADDR_NON      C                   -1
  68.       *
  69.       *
  70.       *-- Socket descritption bits in 4 byte unsigned integers
  71.       *
  72.      D FD_Set          Ds
  73.      D  FDes                         10U 0 Dim(7)
  74.      d  @version       ds                  dtaara(qss1mri)
  75.      d   @vxrx                 1      4a
  76.      d   @vall                 1    750
  77.       *
  78.       *
  79.       *================================================================
  80.       *   S u b p r o c e d u r e   p r o t o t y p e s
  81.       *================================================================
  82.       *
  83.       *
  84.       *-- Socket --- Create a socket ----------------------------------
  85.       *
  86.       *   int socket(int address_family,
  87.       *              int type,
  88.       *              int protocol)
  89.       *
  90.      D Socket          Pr            10I 0 Extproc('socket')
  91.       *
  92.      D                               10I 0 Value
  93.      D                               10I 0 Value
  94.      D                               10I 0 Value
  95.       *
  96.       *
  97.       *-- Setsockopt --- Set socket options
  98.       *
  99.       *   int setsockopt(int socket_descriptor,
  100.       *                  int level,
  101.       *                  int option_name,
  102.       *                  char *option_value,
  103.       *                  int option_length)
  104.       *
  105.      D SetsockOpt      Pr            10I 0 Extproc('setsockopt')
  106.       *
  107.      D                               10I 0 Value
  108.      D                               10I 0 Value
  109.      D                               10I 0 Value
  110.      D                                 *   Value
  111.      D                               10I 0 Value
  112.       *
  113.       *
  114.       *-- InetAddr --- Transform IP address from dotted form ----------
  115.       *
  116.       *   unsigned long inet_addr(char *address_string);
  117.       *
  118.      D InetAddr        Pr            10U 0 ExtProc('inet_addr')
  119.       *
  120.      D                                 *   Value
  121.       *
  122.       *
  123.       *-- GetHostByName --- Get host address from name ----------------
  124.       *
  125.       *   struct HostEnt {
  126.       *      char   *h_name;
  127.       *      char   **h_aliases;
  128.       *      int    h_addrtype;
  129.       *      int    h_length;
  130.       *      char   **h_addr_list;
  131.       *   };
  132.       *
  133.       *   struct HostEnt *GetHostByName(char *host_name);
  134.       *
  135.      D GetHost         Pr              *   Extproc('gethostbyname')
  136.       *
  137.      D                                 *   Value
  138.       *
  139.       *
  140.       *-- Connect --- Connect to the server
  141.       *
  142.       *   int connect(int socket_descriptor,
  143.       *               struct sockaddr *destination_address,
  144.       *               int address_length);
  145.       *
  146.      D Connect         Pr            10I 0 Extproc('connect')
  147.       *
  148.      D                               10I 0 Value
  149.      D                                 *   Value
  150.      D                               10I 0 Value
  151.       *
  152.       *
  153.       *-- FCntl --- File control for I/O
  154.       *
  155.       *   int fcntl(int file_descriptor, int cmd, . . .);
  156.       *
  157.      D FCntl           Pr            10I 0 Extproc('fcntl')
  158.       *
  159.      D                               10I 0 Value
  160.      D F_SETFL                       10I 0 Value
  161.      D O_NONBLOCK                    10I 0 Value  Options(*Nopass)
  162.       *
  163.       *
  164.       *-- FDzero --- Zero socket description bit (for Select function)
  165.       *
  166.       *   #define FD_ZERO(fds)  (memset(fds,0,sizeof(fd_set)))
  167.       *
  168.      D FDZero          Pr
  169.       *
  170.      D  FDes                         10U 0 Dim(7)
  171.       *
  172.       *
  173.       *-- FDSet --- Set socket description bit (for Select function)
  174.       *
  175.       *   #define FD_SET(fd, fds)  \
  176.       *         set bits
  177.       *
  178.      D FDSet           Pr
  179.       *
  180.      D  FD                           10I 0 Value
  181.      D  FDes                         10U 0 Dim(7)
  182.       *
  183.       *
  184.       *-- FDClr --- Clear socket description bit (for Select function)
  185.       *
  186.       *   #define FD_CLR(fd, fds)   \
  187.       *
  188.       *
  189.      D FDClr           Pr
  190.       *
  191.      D  FD                           10I 0 Value
  192.      D  FDes                         10U 0 Dim(7)
  193.       *
  194.       *
  195.       *-- FDIsSet --- Test if a socket description bit is set on
  196.       *               (for Select function)
  197.       *
  198.       *   #define FD_ISSET(fd, fds)  \
  199.       *
  200.       *
  201.      D FDIsSet         Pr            10I 0
  202.       *
  203.      D  FD                           10I 0 Value
  204.      D  FDes                         10U 0 Dim(7)
  205.       *
  206.       *
  207.       *-- Select -  Wait for events on multiple sockets
  208.       *             and set bits for active sockets
  209.       *
  210.       *   int select(int max_descriptor,
  211.       *              fd_set *read_set,
  212.       *              fd_set *write_set,
  213.       *              fd_set *exception_set,
  214.       *              struct timeval *wait_time);
  215.       *
  216.       *
  217.       *
  218.       *-- Read --- Read data from the socket
  219.       *
  220.       *   ssize_t read(int descriptor,
  221.       *                void *buffer,
  222.       *                size_t buffer_length);
  223.       *
  224.      D Read            Pr            10I 0 Extproc('read')
  225.       *
  226.      D                               10I 0 Value
  227.      D                                 *   Value
  228.      D                               10U 0 Value
  229.       *
  230.       *
  231.       *-- Recv --- Receive data from the socket
  232.       *
  233.       *   int recv(int descriptor,
  234.       *            char *buffer,
  235.       *            int  buffer_length,
  236.       *            int  flags);
  237.       *
  238.      D Recv            Pr            10I 0 Extproc('recv')
  239.       *
  240.      D                               10I 0 Value
  241.      D                                 *   Value
  242.      D                               10I 0 Value
  243.      D                               10I 0 Value
  244.       *
  245.       *
  246.       *-- Write --- Write data to the socket
  247.       *
  248.       *   ssize_t write(int file_descriptor,
  249.       *                 const void *buffer,
  250.       *                 size_t buffer_length);
  251.       *
  252.      D Write           Pr            10I 0 ExtProc('write')
  253.       *
  254.      D                               10I 0 Value
  255.      D                                 *   Value
  256.      D                               10U 0 Value
  257.       *
  258.       *
  259.       *
  260.       * Prototype for DspError subprocedure
  261.      DDspError         PR
  262.      D text                          10A   Const
  263.       *-- Open --- Open the socket
  264.      D open            PR            10I 0 ExtProc('open')
  265.      D  pathptrp                       *   value
  266.      D  oflag                        10I 0 Value
  267.      D  mode                         10U 0 Value Options(*nopass)
  268.      D  codepage                     10U 0 Value Options(*nopass)
  269.       *
  270.       *
  271.       *-- Send --- Send data to the socket
  272.       *
  273.       *   int send(int  descriptor,
  274.       *            char *buffer,
  275.       *            int  buffer_length,
  276.       *            int  flags);
  277.       *
  278.      D Send            Pr            10I 0 ExtProc('send')
  279.       *
  280.      D                               10I 0 Value
  281.      D                                 *   Value
  282.      D                               10I 0 Value
  283.      D                               10I 0 Value
  284.       *
  285.       *
  286.       *-- Close --- Close a socket
  287.       *
  288.       *   int close(int descriptor)
  289.       *
  290.      D Close           Pr                  ExtProc('close')
  291.       *
  292.      D                               10I 0 Value
  293.       *
  294.       *
  295.       *-- GetErrNo ---- Get error number ----------------------------------
  296.       *
  297.       *   extern int * __errno(void);
  298.       *
  299.      D GetErrNo        Pr              *   ExtProc('__errno')
  300.       *
  301.       *
  302.       *-- StrError ---- Get error text ------------------------------------
  303.       *
  304.       *   char *strerror(int errnum);
  305.       *
  306.      D StrError        Pr              *   ExtProc('strerror')
  307.       *
  308.      D                               10I 0 Value
  309.       *
  310.       *
  311.       *-- Sleep --- Sleep function (delay job) ------------------------
  312.       *
  313.       *   unsigned int sleep( unsigned int seconds );
  314.       *
  315.      D Sleep           Pr            10U 0 ExtProc('sleep')
  316.       *
  317.      D                               10U 0 Value
  318.       *
  319.       *
  320.      D Translate       PR                  ExtPgm('QDCXLATE')
  321.      D  Length                        5p 0 CONST
  322.      D  XDATA                     32767A   options(*varsize)
  323.      D  Table                        10a   CONST
  324.       *
  325.       *   ReadSocket subprocedure prototype
  326.      D ReadSocket      Pr            10I 0
  327.      D  SD                           10I 0 Value
  328.      D  SockData@                      *   Value
  329.      D  SockDtaLen                   10I 0 Value
  330.      D  Retry                        10I 0 Value
  331.       *
  332.       *   WriteSocket subprocedure prototype
  333.      D WriteSock       Pr            10I 0
  334.      D  SD                           10I 0 Value
  335.      D  SockData@                      *   Value
  336.      D  SockDtaLen                   10I 0 Value
  337.      D  Retry                        10I 0 Value
  338.       *
  339.       *   Port number
  340.      D PortNumber      S              5u 0
  341.       *   Socket description number for the client
  342.      D SD              S             10I 0
  343.       *   Return code for sockets
  344.      D RC              S             10I 0
  345.       *   Option name for SetSockOpt function
  346.      D OptVal          S             10U 0 Inz(1)
  347.       *   Server IP address in dotted form
  348.      D ServerAddr      S             15A
  349.       *
  350.       *   Error handling subprocedure prototype
  351.      D ErrorHdlr       Pr
  352.      D DumpText                      12    Value
  353.  
  354.  
  355.  
  356.      d @Error          s             10a
  357.      d @Trans          s             50a
  358.       *
  359.       *==================================================================
  360.       *   M A I N   P R O G R A M
  361.       *==================================================================
  362.       *
  363.       *
  364.       *
  365.       *
  366.       *   Obtain a socket descriptor
  367.      c                   Eval      Sd = socket(af_inet: sock_str: 0)
  368.       *
  369.       *   If socket failed - End the client program with dump
  370.      c                   If        Sd < 0
  371.      c                   Callp     Errorhdlr ('ClientSocket')
  372.      C                   Eval      *inlr = *On
  373.      c                   Return
  374.      c                   Endif                                                  ž If sd < 0
  375.       *
  376.       *   Allow socket description to be reusable
  377.      c                   Eval      Rc = setsockopt(sd: sol_socket
  378.      C                                               : SO_REUSEAD
  379.      C                                               : %Addr(OptVal)
  380.      C                                               : %Size(OptVal))
  381.       *
  382.       *   If SetSockOpt failed - End the server with dump
  383.      c                   If        Rc < 0
  384.      c                   Callp     Errorhdlr ('SetSockOpt')
  385.      C                   CallP     Close(SD)
  386.      C                   Eval      *inlr = *on
  387.      c                   Return
  388.      c                   Endif                                                  ž If rc < 0
  389.       *
  390.       *   Fill in necessary fields in the IP address structure
  391.      c                   Eval      Socketaddr = *allx'00'
  392.      c                   Eval      Sinfamily = af_inet
  393.       *   Get the version of OS400 so we can work around IBM's dumbness
  394.      c                   In        @version
  395.      c                   Unlock    @version
  396.      c                   If        @vxrx = 'V4R3'
  397.      c                   Eval      Portnumber = 46167
  398.      c                   Else                                                    If @vxrx = 'V4R3'
  399.      c                   Eval      Portnumber = 56167
  400.      c                   Endif                                                  ž If @vxrx = 'V4R3'
  401.      c                   Eval      Sinport = portnumber
  402.       *
  403.       *   Copy the IP address from the host entry structure into
  404.       *   the server IP address structure
  405.      c                   Eval      Serveraddr = '172.24.1.36'
  406.      c                   Eval      Sinaddr = inetaddr(%addr(serveraddr))
  407.       *
  408.       *   Connect to the server
  409.      c                   Eval      Rc = connect( sd:
  410.      C                                           %Addr(SocketAddr):
  411.      C                                           %Size(SocketAddr))
  412.       *   If connect unsuccessful - Enter recovery loop
  413.      c                   If        Rc < 0
  414.      c                   Eval      *inlr = *on
  415.      c                   Eval      @error = 'NOSERV'
  416.      c                   Callp     Close(sd)
  417.      c                   Return
  418.      c                   Endif                                                  ž If rc < 0
  419.       *
  420.       *   Set nonblocked mode for the socket
  421.      c                   Eval      Rc = fcntl(sd: f_setfl: o_nonblock)
  422.       *
  423.       *   If FCntl failed - End the server with dump
  424.      c                   If        Rc < 0
  425.      c                   Callp     Errorhdlr ('SvrFCntl')
  426.      C                   CallP     Close(SD)
  427.      C                   Eval      *inlr = *on
  428.      c                   Return
  429.      c                   Endif                                                  ž If rc < 0
  430.       *
  431.       *
  432.       *   Send the string to the server over the socket
  433.      c                   Eval      @trans = 'TESTING 123'
  434.      c                   Callp     Translate(50:@trans:'QTCPASC')
  435.      c                   Eval      Rc = writesock(sd: %addr(@trans)
  436.      C                                                : 50 : 5)
  437.       *   If write failed - Enter recovery loop
  438.      c                   If        Rc < 0
  439.      c                   Callp     Errorhdlr ('SendMode')
  440.      C                   CallP     Close(SD)
  441.      C                   Eval      *inlr = *on
  442.      c                   Return
  443.      c                   Endif                                                  ž If rc < 0
  444.      C                   CallP     Close(SD)
  445.      C                   Eval      *inlr = *on
  446.      c                   Return
  447.       *=====================================================================
  448.       *   S U B P R O C E D U R E   D E F I N I T I O N S
  449.       *=====================================================================
  450.       *
  451.       *---------------------------------------------------------------------
  452.       *   ErrorHdlr - Error handling subprocedure -
  453.       *               prints a storage dump.
  454.       *               The input parameter is a text to recognize the dump.
  455.       *               No return value is provided.
  456.       *---------------------------------------------------------------------
  457.       *
  458.      PErrorHdlr        B
  459.       *
  460.       *   Error handling subprocedure prototype
  461.      D ErrorHdlr       Pr
  462.      D DumpText                      12    Value
  463.       *
  464.       *   Error handling subprocedure interface
  465.      D ErrorHdlr       PI
  466.      D DumpText                      12    Value
  467.       *
  468.      c                   Eval      Errno@ = geterrno
  469.      c                   Eval      Errmsg@ = strerror(errno)
  470.       *
  471.      c     dumptext      Dump
  472.      c                   Callp     Close(sd)
  473.      c                   Eval      *inlr=*on
  474.       *
  475.      PErrorHdlr        E
  476.       *
  477.       *----------------------------------------------------------------
  478.       *   ReadSocket - Read socket with recovery
  479.       *----------------------------------------------------------------
  480.       *
  481.      PReadSocket       B                   EXPORT
  482.       *
  483.       *   ReadSocket subprocedure prototype
  484.      D ReadSocket      Pr            10I 0
  485.      D  SD                           10I 0 Value
  486.      D  SockData@                      *   Value
  487.      D  SockDataLn                   10I 0 Value
  488.      D  Retry                        10I 0 Value
  489.       *
  490.       *   ReadSocket subprocedure interface
  491.      D ReadSocket      PI            10I 0
  492.      D  SD                           10I 0 Value
  493.      D  SockData@                      *   Value
  494.      D  SockDataLn                   10I 0 Value
  495.      D  Retry                        10I 0 Value
  496.       *
  497.      D RC              S             10I 0
  498.       *
  499.      c                   Do        retry                                        Begin DO
  500.       *
  501.      c                   Eval      Errno@ = geterrno
  502.       *
  503.      c                   Eval      Errno = 0
  504.       *
  505.      c                   Eval      Rc = read (sd: sockdata@: sockdataln)
  506.       *
  507.      c                   Eval      Errno@ = geterrno
  508.      c                   Eval      Errmsg@ = strerror(errno)
  509.       *
  510.      c                   Dow       errno = ewouldblck                           Begin DO
  511.       *
  512.      c                   Callp     Sleep (1)
  513.       *
  514.      c                   Eval      Rc = read (sd: sockdata@: sockdataln)
  515.       *
  516.      c                   Eval      Errno@ = geterrno
  517.      c                   Eval      Errmsg@ = strerror(errno)
  518.       *
  519.      c                   Enddo                                                   Dow errno = ewould
  520.       *
  521.      c                   If        Rc > 0
  522.      c                   Return    Rc
  523.      c                   Endif                                                  ž If rc > 0
  524.       *
  525.      c                   Enddo                                                   Do retry
  526.       *
  527.      c                   Return    Rc
  528.       *
  529.      PReadSocket       E
  530.       *
  531.       *----------------------------------------------------------------
  532.       *   WriteSocket - Write socket with recovery
  533.       *----------------------------------------------------------------
  534.       *
  535.      PWriteSock        B                   EXPORT
  536.       *
  537.       *   WriteSocket subprocedure prototype
  538.      D WriteSock       Pr            10I 0
  539.      D  SD                           10I 0 Value
  540.      D  SockData@                      *   Value
  541.      D  SockDataLn                   10I 0 Value
  542.      D  Retry                        10I 0 Value
  543.       *
  544.       *   WriteSocket subprocedure interface
  545.      D WriteSock       PI            10I 0
  546.      D  SD                           10I 0 Value
  547.      D  SockData@                      *   Value
  548.      D  SockDataLn                   10I 0 Value
  549.      D  Retry                        10I 0 Value
  550.       *
  551.      D RC              S             10I 0
  552.       *
  553.      c                   Do        retry                                        Begin DO
  554.       *
  555.      c                   Eval      Errno@ = geterrno
  556.       *
  557.      c                   Eval      Errno = 0
  558.       *
  559.      c                   Eval      Rc = write(sd: sockdata@: sockdataln)
  560.       *
  561.      c                   Eval      Errno@ = geterrno
  562.      c                   Eval      Errmsg@ = strerror(errno)
  563.       *
  564.      c                   Dow       errno = ewouldblck                           Begin DO
  565.       *
  566.      c                   Callp     Sleep (1)
  567.      c                   Eval      Rc = write(sd: sockdata@: sockdataln)
  568.       *
  569.      c                   Eval      Errno@ = geterrno
  570.      c                   Eval      Errmsg@ = strerror(errno)
  571.       *
  572.      c                   Enddo                                                   Dow errno = ewould
  573.      c                   If        Rc > 0
  574.      c                   Return    Rc
  575.      c                   Endif                                                  ž If rc > 0
  576.       *
  577.      c                   Enddo                                                   Do retry
  578.       *
  579.      c                   Return    Rc
  580.       *
  581.      PWriteSock        E
  582.       *
  583.      PDspError         B
  584.      DDspError         PI
  585.      D text                          10A   Const
  586.       *
  587.       * Variables for __errno() and strerror() APIs
  588.      DerrorNo@         S               *   Inz
  589.      D errorNo         S             10I 0 Based(Errorno@)
  590.      DerrorMsg@        S               *   Inz
  591.      D errorMsg        S            100A   Based(errorMsg@)
  592.      Derrortxt         S             52A   Inz(*blank)
  593.      Derrorchar        s             10a
  594.       *
  595.      c                   Eval      Errorno@ = geterrno
  596.      c                   Eval      Errormsg@ = strerror(errorno)
  597.      c                   Move      Errorno       errorchar
  598.      c                   Eval      Errortxt =%trim(text) + '->' +
  599.      C                                         errorchar
  600.      C                             + ':' + %subst(errormsg : 1 : 37)
  601.      c     errortxt      Dsply
  602.      P                 E 
© 2004-2019 by midrange.com generated in 0.009s valid xhtml & css