The last several topics have added a lot of improvements to our client program. The result will be something that you could even adapt to your own needs if you wanted an AS/400 program that would fetch web documents.
Here's the new improved sample http client:
File: SOCKTUT/QRPGLESRC, Member: CLIENTEX2
H DFTACTGRP(*NO) ACTGRP(*NEW) H BNDDIR('QC2LE') BNDDIR('SOCKTUT/SOCKUTIL') D/copy socktut/qrpglesrc,socket_h D/copy socktut/qrpglesrc,errno_h D/copy socktut/qrpglesrc,sockutil_h ********************************************************* * Definitions needed to make IFS API calls. Note that * these should really be in a separate /copy file! ********************************************************* D O_WRONLY C 2 D O_CREAT C 8 D O_TRUNC C 64 D O_CODEPAGE C 8388608 D open PR 10I 0 ExtProc('open') D filename * value options(*string) D openflags 10I 0 value D mode 10U 0 value options(*nopass) D codepage 10U 0 value options(*nopass) D unlink PR 10I 0 ExtProc('unlink') D path * Value options(*string) D write PR 10I 0 ExtProc('write') D handle 10I 0 value D buffer * value D bytes 10U 0 value ********************************************************* * end of IFS API call definitions ********************************************************* D die PR D peMsg 256A const D cmd PR ExtPgm('QCMDEXC') D command 200A const D length 15P 5 const D msg S 50A D sock S 10I 0 D port S 5U 0 D addrlen S 10I 0 D ch S 1A D host s 32A D file s 32A D addr s 10U 0 D p_Connto S * D RC S 10I 0 D RecBuf S 50A D RecLen S 10I 0 D err S 10I 0 D fd S 10I 0 C************************************************* C* The user will supply a hostname and file C* name as parameters to our program... C************************************************* c *entry plist c parm host c parm file c eval *inlr = *on C************************************************* C* what port is the http service located on? C************************************************* c eval p_servent = getservbyname('http':'tcp') c if p_servent = *NULL c callp die('Can''t find the HTTP service!') c return c endif c eval port = s_port C************************************************* C* Get the 32-bit network IP address for the host C* that was supplied by the user: C************************************************* c eval addr = inet_addr(%trim(host)) c if addr = INADDR_NONE c eval p_hostent = gethostbyname(%trim(host)) c if p_hostent = *NULL c callp die('Unable to find that host!') c return c endif c eval addr = h_addr c endif C************************************************* C* Create a socket C************************************************* c eval sock = socket(AF_INET: SOCK_STREAM: c IPPROTO_IP) c if sock < 0 c callp die('socket(): ' + %str(strerror(errno))) c return c endif C************************************************* C* Create a socket address structure that C* describes the host & port we wanted to C* connect to C************************************************* c eval addrlen = %size(sockaddr) c alloc addrlen p_connto c eval p_sockaddr = p_connto c eval sin_family = AF_INET c eval sin_addr = addr c eval sin_port = port c eval sin_zero = *ALLx'00' C************************************************* C* Connect to the requested host C************************************************* C if connect(sock: p_connto: addrlen) < 0 c eval err = errno c callp close(sock) c callp die('connect(): '+%str(strerror(err))) c return c endif C************************************************* C* Send a request for the file that we'd like C* the http server to send us. C* C* Then we send a blank line to tell it we're C* done sending requests, it can process them... C************************************************* c callp WrLine(sock: 'GET http://' + c %trim(host) + %trim(file) + c ' HTTP/1.0') c callp WrLine(sock: ' ') C************************************************* C* Get back the server's response codes C* C* The HTTP server will send it's responses one C* by one, then send a blank line to separate C* the server responses from the actual data. C************************************************* c dou recbuf = *blanks C eval rc = rdline(sock: %addr(recbuf): c %size(recbuf): *On) c if rc < 0 c eval err = errno c callp close(sock) c callp die('rdline(): '+%str(strerror(err))) c return c endif c enddo C************************************************* C* Open a temporary stream file to put our C* web page data into: C************************************************* c eval fd = open('/http_tempfile.txt': c O_WRONLY+O_TRUNC+O_CREAT+O_CODEPAGE: c 511: 437) c if fd < 0 c eval err = errno c callp close(sock) c callp Die('open(): '+%str(strerror(err))) c return c endif C************************************************* C* Write returned data to the stream file: C************************************************* c dou rc < 1 c eval rc = recv(sock: %addr(recbuf): c %size(recbuf): 0) c if rc > 0 c callp write(fd: %addr(recbuf): rc) c endif c enddo C************************************************* C* We're done receiving, do the following: C* 1) close the stream file & socket. C* 2) display the stream file C* 3) unlink (delete) the stream file C* 4) end program C************************************************* c callp close(fd) c callp close(sock) c callp Cmd('DSPF STMF(''/http_tempfile.txt'')': c 200) c callp unlink('/http_tempfile.txt') c return *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * This ends this program abnormally, and sends back an escape. * message explaining the failure. *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ P die B D die PI D peMsg 256A const D SndPgmMsg PR ExtPgm('QMHSNDPM') D MessageID 7A Const D QualMsgF 20A Const D MsgData 256A Const D MsgDtaLen 10I 0 Const D MsgType 10A Const D CallStkEnt 10A Const D CallStkCnt 10I 0 Const D MessageKey 4A D ErrorCode 32766A options(*varsize) D dsEC DS D dsECBytesP 1 4I 0 INZ(256) D dsECBytesA 5 8I 0 INZ(0) D dsECMsgID 9 15 D dsECReserv 16 16 D dsECMsgDta 17 256 D wwMsgLen S 10I 0 D wwTheKey S 4A c eval wwMsgLen = %len(%trimr(peMsg)) c if wwMsgLen<1 c return c endif c callp SndPgmMsg('CPF9897': 'QCPFMSG *LIBL': c peMsg: wwMsgLen: '*ESCAPE': c '*PGMBDY': 1: wwTheKey: dsEC) c return P E /define ERRNO_LOAD_PROCEDURE /copy socktut/qrpglesrc,errno_h