Socket Open/Create

Essentials

This section summarises the content on this page (read on for the full tutorial):

Socket

A "create socket", "open socket" or simply "socket" request (or API call) is required before any other client/server communication oriented requests can be made, it enables the API to establish linkage between the application and all future related communications. The API returns a socket number (0 is a valid socket number) which the application and the API exchange on all future application requests and API postings/notifications.

Across all language implementations the following parameters will typically be required:

Address FamilyThis refers to the network addressing structure of the future connections to be established. Predefined constants are normally available for this with AF_INET being used to define IP V4 network connections and AF_INET6 for IP V6. With this the stack knows how to read the IP address passed on your bind and/or connect requests.
TypeSpecifies the type of data to be transferred on established connections, with typical predefined values as SOCK_STREAM standard for TCP, SOCK_DGRAM for UDP and SOCK_RAW for application defined protocols such as ICMP.
ProtocolMay usually be defaulted (based on family and type above) or specified as IPPROTO_TCP, IPPROTO_UDP or IPPROTO_ICMP as required.

Returns: in line with common UNIX programming the call will return a code which if negative indicates an error occurred. The exact error is returned as ERRNO a second returned value made available to the calling program, see the examples below for details. If the returned code is zero or a positive number then this is the socket number, to be used by the application and the stack when exchanging request information across the API.

The socket call is so fundamental that many coding examples will assume correct processing, such a practise may well be the cause of great pain at some future point and should be avoided.

Note that socket open processing can be usefully placed inside a loop that processes returned entries from GetAddrInfo. GetAddrInfo returns the address family and therefore allows a client to be address family independent when establishing connections.

Client
Connections
Next
Sockets
Contents
Contents
Introduction
Prev

Example Socket Calls

Follow the below links for examples applicable to your preferred environment:

UNIX
C
PHP
Lua
ooREXX
IBM TSO
REXX
IBM HPNS
HLASM

C (generic UNIX)

After including the relevant header files our C code can simply call the socket function to create a socket.


#include <sys/types.h>
#include <sys/socket.h>
	
int socketOpen() {
    int fd;

    if ((fd = socket( AF_INET, SOCK_STREAM, 0)) < 0) {
        printf("Cannot open socket");
        return -1;
    }
    return fd;
}

A better solution is to open a socket based on the output from a getaddrinfo() call. This permits simplified support for both IPv4 and IPv6 connections.

You can see this approach in the full client program here

PHP

Sockets support is a PHP compile time option and in most cases this is not supported. This will be the only example of using the sockets API with PHP. Use the generic C examples as a guide for other calls.

try {
    if (!$socNum = socket_create( AF_INET, SOCK_STREAM, 0 )) {
        echo 'Failed to create socket ('.socket_last_error().'): '
            .socket_strerror(socket_last_error());
        exit(4);
    }
} 
catch (Error $e) {
    echo 'Looks like sockets are not supported on this compile of PHP: '
        .$e->getMessage();
    exit(8);
}

Lua

Lua support for sockets is available through the luasockets library. This is included in your script through a 'require "socket"' or 'require "luasocket"' depending on your installation.

Lua sockets support is via a TCP object (TCP thus identifying the socket type and protocol), a master object is initialized and this is converted to a client object (or server object) based on the socket calls made. Creation of the master object is similar to a socket open request as illustrated below.


   clnt, emsg = socket.tcp();
   if ( not clnt) then
      print( "Unable to create TCP object: " .. emsg);
   end;

This code and a subsequent connect can be replaced by the Lua functions 'assert( socket.connect( host, port))'. Error handling and messages are Lua determined but provide sufficient information for simple scripts.

ooREXX

Before invoking socket functions we must have added and called SockLoadFuncs to load the individual functions forming the sockets API. The function package is then initialized via a SockInit call, after which a socket can be opened as shown in the example:

You can see the full program here


/*********************************************************************/
/*  Open the socket                                                  */
/*********************************************************************/
  socNum = SockSocket("AF_INET", "SOCK_STREAM", "IPPROTO_TCP")
  if ( socNum < 0) then do
      say 'Error opening socket, ERRNO:' errno
      exit
  end

Note that errno is a special variable maintained by the RxSock implementation.

IBM TSO REXX

Before invoking the socket functions we must have initialized the API through a Socket Initialize call. After a successful open and if desired, the SETSOCKOPT SO_ASCII function would normally be invoked to allow automatic translation of sent and received data between EBCDIC and ASCII.

You can see the full program here

/*********************************************************************/
/*  Open the socket                                                  */
/*********************************************************************/
  Resp = SOCKET('SOCKET', 'AF_INET', 'SOCK_STREAM', 'IPPROTO_TCP')
  if WORD( resp, 1) <> 0 then do
      say 'Error opening socket'
      say resp
      exit
  end
  SocNum = WORD( resp, 2)

IBM HPNS API

IBM's High Performance Network Sockets (HPNS) API uses the EZASMI macro to make API requests. Before issuing this SOCKET request the API will need to have been initialized, an EZASMI INITAPI call with (in our case) APITYPE=2 synchronous requests.

You can see the full program here

This snippet is shown as a subroutine with base addressability via R12, required for the EZASMI call. Note on successful completion the socket number (returned via retcode) is saved as a halfword value in the connection control block. This will be input to all API requests related to this established connection.

********************************************************************** 
* Open a socket for the passed CWA                                   * 
********************************************************************** 
         USING WORK_AREA_1,R13
         USING CWA_BLOCK,R9 
DO_SOCKET DS   0H                      ******************************* 
         STMG  R0,R15,W1_SAV2          * Save callers regs           * 
         MVC   CWA_REQNM,=CL12'SOCKET' * Request name                * 
         MVC   CWA_PLIST(MODEL_EZASMI_LENGTH),MODEL_EZASMI init plst * 
         EZASMI TYPE=SOCKET,           *                             * X 
               AF='INET',              *                             * X 
               SOCTYPE='STREAM',       *                             * X 
               TASK=W1T_TASK_WA,       *                             * X 
               ERRNO=CWA_ERRNO,        *                             * X 
               RETCODE=CWA_RETCD,      *                             * X 
               MF=(E,CWA_PLIST)        *                             * 
         LGF   R15,CWA_RETCD           * Pick up return code         * 
         LTGR  R15,R15                 * Check value                 * 
         JM    SOCK_REQ_ERR            * Negative - record error     * 
         STH   R15,CWA_SOCNO           * Save socket number          * 
         OI    CWA_STATE,CWA_STATE_OPEN  Flag socket open            * 
         J     SOCK_RET                * Y - skip err msg            * 
****************************************                             * 
* EZASMI call error processing, issue message set return code        * 
****************************************                             * 
SOCK_REQ_ERR DS 0H                     *                             * 
         JAS   R14,DO_REQ_ERR          * Go report error             * 
         LA    R15,16                  * Return code                 * 
SOCK_RET DS    0H                      *                             * 
         LMG   R0,R14,W1_SAV2          * Restore callers regs        * 
         BR    R14                     * Return                      * 
*                                      ******************************* 
         DROP  R9,R13


**********************************************************************
* Program constants                                                  *
**********************************************************************		 
MODEL_EZASMI EZASMI MF=L               *                             * 
MODEL_EZASMI_LENGTH EQU *-MODEL_EZASMI *                             * 


****************************************                             * 
* Work Area 1 LOC=ANY                                                * 
****************************************                             * 
WORK_AREA_1 DSECT ,                    *                             * 
W1_SAVE  DS    18D                     * Standard save area          * 
W1_SAV2  DS    16D                     * Subroutine save area        * 

W1T_TASK_WA DS XL(TIELENTH)            *                             * 

**********************************************************************  
* CWA - Connection Work Area                                         *  
**********************************************************************  
CWA_BLOCK DSECT ,                      ******************************* 
CWA_ID    DS   CL2                     * CB                          * 
CWA_LEN   DS   H                       * length                      * 
CWA_CONN_NAME DS CL64                  *                             * 
CWA_SBUF  DS   A                       * Send buffer address         * 
CWA_RBUF  DS   A                       * Recv buffer address         * 
CWA_PLIST DS   XL(MODEL_EZASMI_LENGTH) *                             * 
CWA_SOCKET DS  0F                      * Fwd socket number           * 
         DS    H                       *                             * 
CWA_SOCNO DS   H                       * Hwd socket number           * 
CWA_RMT_ADDR DS XL(SOCK#LEN+SOCK_SIN#LEN) IPV4 address structure     * 
CWA_RETCD DS   F                       * Return code                 * 
CWA_ERRNO DS   F                       * Error Number (RetCd = -1)   * 
CWA_ECB  DS    F                       * Request ECB                 * 
         DS    XL100                   * HPNS work area (contig ECB) * 
CWA_REQNM DS   CL12                    * Request name for log/trace  * 
CWA_ROLE DS    C                       * L, S or C                   * 
CWA_STATE DS   X                       * State flags                 * 
CWA_STATE_OPEN   EQU B'10000000'       * Socket is open              * 
CWA_STATE_CONN   EQU B'01000000'       * Socket is connected         * 
CWA_STATE_SRTY   EQU B'00000001'       * Send retry in progress      * 
CWA_STATE_DUMP   EQU B'00100000'       * 0C1 when on                 * 
         DS    0D                      *                             * 
CWA_BLOCK_LENGTH EQU *-CWA_BLOCK       *                             * 

 

Client
Connections
Next
Sockets
Contents
Contents
Introduction
Prev