The Lightsabre Project ====================== Part 003 - Sending and Receiving Another weekend, another couple of hours bashing on COBOL. The client now makes a connection, asks for the top document (sending an empty CRLF) then prints out what it received. Here's a screen shot (the contents of the SYSOUT spool dataset): ********************************* TOP OF DATA ********************************** gopher for mvs initializing sockets api getting foreign host IP hostname-value republic.circumlunar.space hostname-length 0026 hostaddr-value 10753750 getting socket connecting to remote server... sending request to remote gophper server... reading data... read: retcode = 0, done. displaying data iWelcome to the Mare Serenitatis Circumlunar Corporate Republic TITLE null.host . \ / null.host 1 i . . / \ * null.host 1 i i ==================-+-+-+-+-+-+-+-+-+-+================== null.host 1 i /\/\/\/\//++++++ null.host 1 i \_______ .oo. . . . .oo._____ \_______ oooo _______/ null.host 1 i . | \||||/ | | [++++] | null.host 1 i * }:{ | (((II))) * null.host 1 i . i . \::/ null.host 1 i (((((oo))))) null.host 1 i * \ / . . YY null.host 1 i / \ /\ n /><\ null.host 1 i !----------|UU|----------! null.hos /__________| null.host 1 i . ++ null.host 1 i null.host 1 i . . null.host 1 i st 1 i null.host 1 i null.host 1 i null.host 1 1About this Server /about er Colony Zaibatsu / zaibatsu.circumlunar.space 70 0Signup for a Republic user .space 70 i null.host 1 1Recent Phlog Updates /updates republic.circumlunar.s d asylum here: null.host 1 i null.host 1 1aidanh010 /~aidanh010 republic.cir republic.circumlunar.space 70 1ben /~ben republic.circumlunar.space 70 1cleber 1emar /~emar republic.circumlunar.space 70 1katolaz /~katolaz republic.circuml ircumlunar.space 70 1kst /~kst republic.circumlunar.space 70 1leeb /~leeb repu republic.circumlunar.space 70 1mijk /~mijk republic.circumlunar.space 70 1mrgu 70 1np89 /~np89 republic.circumlunar.space 70 1rond /~rond republic.circumlun ircumlunar.space 70 1uwu /~uwu republic.circumlunar.space 70 . closing socket terminating sockets api done! ******************************** BOTTOM OF DATA ******************************** So, I can make requests to the gopher server and receive stuff back. Excellent. A lazy man might call it a day there and say 'job done', gopher client *technically* written. I'm going to put a bit more effort in than that, however :) republic.circumlunar.space is an ASCII system and MVS is EBCDIC, so anything sent and received needs to be translated on its way in and out. Fortunately, the sockets API provides two functions to do this for me: EZACIC04 and EZACIC05. Snappy names, aren't they? They're pretty straightforward to use. To send the top page CRLF to the server, I move EBCDIC into a buffer, call EZACIC04 with the buffer and the buffer length, and it returns ASCII data to me in the same buffer: move X"0D25" to send-empty. move 2 to send-bytes-remain. call 'EZACIC04' using send-empty send-bytes-remain. 'send-empty' is the data buffer X"0D25" is EBCDIC hex code for CR and LF 'send-bytes-remain' is the length of the buffer (which also doubles as the counter for bytes read for the socket write call further down the code) Reading stuff back is much the same, only going from ASCII to EBCDIC via EZACIC05: call 'EZACIC05' using read-buffer recv-bytes-read. display read-buffer(1:recv-bytes-read). Earlier in the code, a socket read call is made, depositing the received ASCII in 'read-buffer', and the number of bytes read into 'recv-bytes-read'. Pass these over to EZACIC05, and it transforms the ASCII in-place to EBCDIC, which then gets printed out. The output is all mashed together because COBOL only starts a new line with each 'display' statement. At the moment I'm dumping the entire buffer out at once. Soon fix that though - 'inspect' is going to count the lines for me, and I think 'unstring' and a variable-length table will help me get things looking a bit better.