The NetRexx Tutorial
- Socket and Networking
NetRexx Tutorial - Socket and Networking


Socket and Networking

Introduction

 
 *** This section is: 
  
 *** and will be available in next releases

Basic Concepts

The socket

Common Operations

Getting your HOST name.

One of the first things you will want to do, is to determine your machine name, i.e. doing in NetRexx what you normally get on your shell typing hostname.

You need to use the class InetAddress, in order to gather your current HOST name, with a call like:

 
host = InetAddress.getlocalHost()
 

The following xsock function will accomplish the job, striping out the (probably) unwanted address in numeric format.

 
+----------------------------------------------------------------------+
| -- method......: hostname                                            |86
| -- purpose.....: get the hostname                                    |87
| --                                                                   |88
|   method hostname() public static                                    |89
|     do                                                               |90
|       host = InetAddress.getlocalHost()                              |91
|     catch err = UnknownHostException                                 |92
|       say err                                                        |93
|     end                                                              |94
|     parse host name'/'                                               |95
|     return name                                                      |96
|                                                                      |97
+----------------------------------------------------------------------+
                                              xsock.nrx(Method:hostname)
Download the complete source for the xsock.nrx library

Client/Server applications

a small client-server application

A client is a process (or a program) that sends a message to a server process (or program); it requests the server to perform a task (also called service).

Client programs usually manage the user-interface portion of the application, validate data entered by the user, dispatch requests to server program, and sometimes execute some logic. The client-based process is the front-end of the application that the user sees and interacts with. The client process contains solution-specific logic and provides the interface between the user and the rest of the application system.

A server process executes the client request performing the task the client requested. Server programs generally: receive requests from client

Sometimes server programs execute common or complex business logic. The server-based process "may" run on another machine on the network. This server could be the host operating system or network file server; the server is then provided both file system services and application services. Resuming, the server process acts as a software engine that manages shared resources such as databases, printers, communication links, or high powered-processors. The server process performs the back-end tasks that are common to similar applications.

In this section we examine a very small client-server application.

Our goal is to explain the basics of the client-server model, with the instructions that allows us to connect the client and the server. For this reason all the details about catching errors are ignored.

Our server is a socket application waiting on a port (we randomly choose the number 6001). The server receives a line of information, constituted by 2 numbers (n1 and n2). The server computes the sum (n3) and returns it to the client.

 
client                        server
side                          side
---------                     ----------

CLIENT    ---- n1 n2 -------> SERVER
                              (...)
                              n3 = n1+n2
                              (...)
CLIENT    <----- n3 --------- SERVER

 

 
+----------------------------------------------------------------------+
| -- sserv                                                             |01
| -- a VERY primitive socket server                                    |02
| --                                                                   |03
| port   = int 6001                                                    |04
| listen = ServerSocket null                                           |05
| client = Socket null                                                 |06
|                                                                      |07
| do                                                                   |08
|   say 'Listening on port "'port'".'                                  |09
|   listen = ServerSocket(port)                                        |10
|                                                                      |11
|   -- wait for a client                                               |12
|   -- get the numbers, add them, return to him                        |13
|   --                                                                 |14
|   loop forever                                                       |15
|     say 'Waiting connection'                                         |16
|     client = listen.accept();                                        |17
|                                                                      |18
|     -- we got something                                              |19
|     --                                                               |20
|     say 'Got request from' client.getInetAddress().getHostName() -   |21
|         ||':'client.getPort();                                       |22
|     in = DataInputStream(client.getInputStream());                   |23
|     out = PrintStream(client.getOutputStream());                     |24
|     line = in.readLine();                                            |25
|     if line = 'exit' then leave                                      |26
|     parse line n1 n2                                                 |27
|     say 'Got "'line'".'                                              |28
|     sum = n1+n2                                                      |29
|     out.println(sum);                                                |30
|   end                                                                |31
| catch e=IOException                                                  |32
|   say 'Error:' e'.'                                                  |33
| end                                                                  |34
| exit 0                                                               |35
+----------------------------------------------------------------------+
                                                               sserv.nrx
Download the source for the sserv.nrx example

 
+----------------------------------------------------------------------+
| -- the SIMPLE client                                                 |01
| --                                                                   |02
| parse arg line                                                       |03
| if line = '' then exit 1                                             |04
| port = int 6001                                                      |05
| host = 'pcl307'     -- should be your host name                      |06
| s = Socket null;                                                     |07
| do                                                                   |08
|   s = Socket(host,port);       -- hard wire it                       |09
|   sin = DataInputStream(s.getInputStream());                         |10
|   sout = PrintStream(s.getOutputStream());                           |11
|                                                                      |12
|   sout.println(line)               -- send command                   |13
|   line = sin.readLine();           -- get answer                     |14
|   say line                                                           |15
|   s.close()                                                          |16
| catch e=IOException                                                  |17
|   say 'Error:'e'.'                                                   |18
| end                                                                  |19
| exit 0                                                               |20
+----------------------------------------------------------------------+
                                                               sclie.nrx
Download the source for the sclie.nrx example

A revised finger program

The following code is an implementation of the "classical" finger program as you find on UNIX boxes or on WIN/95 WIN/NT.

 
+----------------------------------------------------------------------+
| -- finger                                                            |01
| --                                                                   |02
|                                                                      |03
| import java.net                                                      |04
| import java.io                                                       |05
|                                                                      |06
| VERSION         = 'v1r001'                                           |07
| AUTHOR          = '(c) P.A.Marchesini, ETHZ'                         |08
| DEFAULT_PORT    = int 79;                                            |09
| CRLF = '\x0D\x0A'                                                    |10
|                                                                      |11
| parse arg uargs                                                      |12
| if uargs = '-h' | uargs = '--help' | uargs = '' then                 |13
|   do                                                                 |14
|     parse source . . myname'.'                                       |15
|     say myname 'version' VERSION AUTHOR                              |16
|     say 'Purpose : sample implementation of a finger client.'        |17
|     say                                                              |18
|     say 'java finger user@system'                                   |19
|     say                                                              |20
|     exit 1;                                                          |21
|   end                                                                |22
|                                                                      |23
| user = ''                                                            |24
| if uargs.pos('@') <> 0                                              |25
|   then parse uargs user'@'node                                      |26
|   else node = uargs                                                  |27
|                                                                      |28
| -- issue the client socket command                                   |29
| --                                                                   |30
| s = Socket null;                                                     |31
| do                                                                   |32
|   s = Socket(node, DEFAULT_PORT);                                    |33
|   sin   = BufferedReader(InputStreamReader(s.getInputStream()))      |34
|   sout  = PrintWriter(s.getOutputStream(),1)                         |35
|   line  = String                                                     |36
|   line  = user||crlf                                                 |37
|   sout.println(line)                                                 |38
|   loop forever                                                       |39
|     line = sin.readLine();                                           |40
|     if (line = null) then do                                         |41
|       leave                                                          |42
|     end                                                              |43
|       say line                                                       |44
|     end                                                              |45
| catch e1 = IOException                                               |46
|   say '# Error from Socket function.'                                |47
|   say '# Message is "'e1'".'                                         |48
|   say '# Abending.'                                                  |49
| finally                                                              |50
|   do                                                                 |51
|     if (s \= null) then s.close()                                    |52
|   catch e1 = IOException                                             |53
|     say '# Error from close.'                                        |54
|     say '# Message is "'e1'".'                                       |55
|     say '# Abending.'                                                |56
|   end                                                                |57
| end                                                                  |58
| exit                                                                 |59
+----------------------------------------------------------------------+
                                                             finger1.nrx
Download the source for the finger1.nrx example

In the following session we'll develop an even shorter version of finger, using the "xsock" libraries.

The "xsock" library.

As I did in the previous (and following) chapters, instead of presenting "dumb" examples, I'll build a small library of socket methods. This library is called xsock.nrx and is available for download on the "usual" WEB directory for libraries.

It should give you enough programming examples to build (eventually) your own socket application. You can of course immediately use it, as shown in the Using the xsock library section.

The "open" method

 
+----------------------------------------------------------------------+
| -- method......: open                                                |57
| -- purpose.....: open a socket                                       |58
| --                                                                   |59
|   method open(host=Rexx,prot=Rexx) public                            |60
|                                                                      |61
|     -- check if the user entered a protocol or a simple              |62
|     -- port number                                                   |63
|     --                                                               |64
|     rc = 0                                                           |65
|     if prot.datatype('D') = 0 then                                   |66
|       do                                                             |67
|         -- he just entered a port with a name,                       |68
|         -- try to find the port, unless abort                        |69
|         dport = getservbyname(prot)                                  |70
|         if dport = -1 then                                           |71
|           do                                                         |72
|             say 'Invalid protocol "'prot'".'                         |73
|             exit 990                                                 |74
|           end                                                        |75
|         port = dport                                                 |76
|         setprotdef(prot)                                             |77
|       end                                                            |78
|     else                                                             |79
|       do                                                             |80
|         -- he just entered a numeric port                            |81
|         -- we need to do nothing                                     |82
|         port = prot                                                  |83
|       end                                                            |84
|                                                                      |85
|     -- do the REAL job                                               |86
|     --                                                               |87
|     do                                                               |88
|       s    = Socket(host, port);                                     |89
|       sin  = BufferedReader(InputStreamReader(s.getInputStream()));  |90
|       sout = PrintWriter(s.getOutputStream(),1);                     |91
|     catch err = IOException                                          |92
|       say err                                                        |93
|     end                                                              |94
|                                                                      |95
+----------------------------------------------------------------------+
                                                  xsock.nrx(Method:open)
Download the complete source for the xsock.nrx library

The "getservbyname" method

 
+----------------------------------------------------------------------+
| -- method......: getservbyname                                       |96
| -- purpose.....:                                                     |97
| --                                                                   |98
|   method getservbyname(serv=Rexx) public static                      |99
|     table = 'DAYTIME 13 FTP  21   TELNET 23'  -                      |00
|             'FINGER  79 NNTP 119  IMAP   143' -                      |01
|             'HTTP    80'                                             |02
|     serv = serv.upper()                                              |03
|     res = -1                                                         |04
|     loop while table <> ''                                           |05
|       parse table sn sp table                                        |06
|       if sn = serv then return sp                                    |07
|     end                                                              |08
|     return res                                                       |09
|                                                                      |10
+----------------------------------------------------------------------+
                                         xsock.nrx(Method:getservbyname)
Download the complete source for the xsock.nrx library

Using the xsock library

Finding info about a protocol

One of the best places to start is:

 
http://www.freesoft.org/Connected/RFC/index.html
 

Writing a daytime client.

 
+----------------------------------------------------------------------+
| /* simple daytime                                                    |01
|  */                                                                  |02
| parse arg node .                                                     |03
| if node = '' then node = 'shift1.cern.ch'                            |04
|                                                                      |05
| so = xsock(node,'DAYTIME')                                           |06
| so.receive()                                                         |07
| so.close()                                                           |08
|                                                                      |09
| exit                                                                 |10
+----------------------------------------------------------------------+
                                                             daytime.nrx
Download the source for the daytime.nrx example

Writing a finger client.

 
+----------------------------------------------------------------------+
| /* simple finger client                                              |01
|  */                                                                  |02
| parse arg what .                                                     |03
| parse what user'@'node                                              |04
| if node = '' then                                                    |05
|   do                                                                 |06
|     say 'finger user@node'                                          |07
|     exit 1                                                           |08
|   end                                                                |09
|                                                                      |10
| so = xsock(node,'FINGER')                                            |11
| so.send(user)                                                        |12
| so.receive()                                                         |13
| so.close()                                                           |14
|                                                                      |15
| exit                                                                 |16
+----------------------------------------------------------------------+
                                                              finger.nrx
Download the source for the finger.nrx example

Writing an FTP client using "sun.net.ftp".

The FTP support is contained in the package sun.net.ftp. The package allows easily to implement an FTP client (to GET and PUT files).

The API documentation can be found at:

 
http://www.java.no/javaBIN/docs/api/sun.net.ftp.FtpClient.html
 

The actual implementation of the FTP client wants to mimic the "standard" UNIX ftp command (which you can find also on Windows/NT). We will call our class xftp and it will be an extention of FtpClient (or sun.net.ftp.FtpClient if you prefer)

To get the functions in the package sun.net.ftp, we need to type:

 
import sun.net.ftp.FtpClient
import sun.net.ftp.FtpInputStream
import sun.net.TelnetInputStream
 

The basic functions are:

 
+----------------------------------------------------------------------+
| -- method......: xget                                                |72
| -- purpose.....: fetch the remote file                               |73
| --                                                                   |74
|   method xget(fids=Rexx) public                                      |75
|     rcclear()                                                        |76
|     parse fids fidr fidl                                             |77
|     if fidl = '' then fidl = fidr                                    |78
|                                                                      |79
|     -- small check: if the local file is there, prompt the user      |80
|     --                                                               |81
|     if xfile.fexist(fidl) & replace = 'NO' then                      |82
|       do                                                             |83
|         say 'Local file "'fidl'" already exists. OK to overwrite? (Y||84
|         if ask.upper <> 'Y' then                                     |85
|           do                                                         |86
|             say 'ABORTED by user.'                                   |87
|             return                                                   |88
|           end                                                        |89
|       end                                                            |90
|                                                                      |91
|     say 'Remote file........:' fidr'.'                               |92
|     say 'Local file.........:' fidl'.'                               |93
|     say 'Transfer type is...:' modeab'.'                             |94
|                                                                      |95
|     buff = byte[16000]                                               |96
|     t = timer()                                                      |97
|     totsize = 0                                                      |98
|     do                                                               |99
|       os = FileOutputStream(fidl)                                    |00
|       tis = host.get(fidr)                                           |01
|       str = '(READING) Tranferred:' totsize 'bytes.'                 |02
|       loop forever                                                   |03
|         System.out.print(str'\x0D')                                  |04
|         n = tis.read(buff)                                           |05
|         if n = -1 then leave     -- there are no more bytes in tis   |06
|         totsize = totsize + n                                        |07
|         str = '(WRITING) Tranferred:' totsize 'bytes.'               |08
|         System.out.print(str'\x0D')                                  |09
|         os.write(buff,0,n)                                           |10
|         str = '(READING) Tranferred:' totsize 'bytes.'               |11
|       end                                                            |12
|       System.out.print('                                     \x0D')  |13
|       say                                                            |14
|       os.close()                                                     |15
|       sec = t.elapsed()                                              |16
|       say 'Transferred "'totsize'" bytes in' sec 'seconds.'          |17
|     catch err = exception                                            |18
|       say 'ERROR:' err                                               |19
|       rcset(12)                                                      |20
|     end                                                              |21
|                                                                      |22
+----------------------------------------------------------------------+
                                                   xftp.nrx(Method:xget)
Download the complete source for the xftp.nrx library

 
+----------------------------------------------------------------------+
| -- method......: xput                                                |23
| -- purpose.....: put the remote file                                 |24
| --                                                                   |25
|   method xput(fids=Rexx) public                                      |26
|     rcclear()                                                        |27
|     parse fids fidl fidr                                             |28
|     if fidr = '' then fidr = fidl                                    |29
|                                                                      |30
|     -- small check: if the local file is not there                   |31
|     --                                                               |32
|     if xfile.fexist(fidl) = 0 then                                   |33
|       do                                                             |34
|         say 'Local file "'fidl'" does not exist.'                    |35
|         return                                                       |36
|       end                                                            |37
|                                                                      |38
|     say 'Local file.........:' fidl'.'                               |39
|     say 'Remote file........:' fidr'.'                               |40
|     say 'Transfer type is...:' modeab'.'                             |41
|                                                                      |42
|     buff = byte[16000]                                               |43
|     t = timer()                                                      |44
|     totsize = 0                                                      |45
|     do                                                               |46
|       is = FileInputStream(fidl)                                     |47
|       tos = host.put(fidr)                                           |48
|       str = '(READING) Tranferred:' totsize 'bytes.'                 |49
|       loop forever                                                   |50
|         System.out.print(str'\x0D')                                  |51
|         n = is.read(buff)                                            |52
|         if n = -1 then leave     -- there are no more bytes in is    |53
|         totsize = totsize + n                                        |54
|         str = '(WRITING) Tranferred:' totsize 'bytes.'               |55
|         System.out.print(str'\x0D')                                  |56
|         tos.write(buff,0,n)                                          |57
|         str = '(READING) Tranferred:' totsize 'bytes.'               |58
|       end                                                            |59
|       System.out.print('                                     \x0D')  |60
|       say                                                            |61
|       tos.close()                                                    |62
|       is.close()                                                     |63
|       sec = t.elapsed()                                              |64
|       say 'Transferred "'totsize'" bytes in' sec 'seconds.'          |65
|     catch err = exception                                            |66
|       say 'ERROR:' err                                               |67
|       rcset(13)                                                      |68
|     end                                                              |69
|                                                                      |70
+----------------------------------------------------------------------+
                                                   xftp.nrx(Method:xput)
Download the complete source for the xftp.nrx library

 
+----------------------------------------------------------------------+
| -- method......: xls                                                 |11
| -- purpose.....: list the remote directory (on screen)               |12
| --                                                                   |13
|   method xls(t=rexx) public                                          |14
|     t = t                                                            |15
|     rcclear()                                                        |16
|     do                                                               |17
|       tis = host.list()                                              |18
|       line = ''                                                      |19
|       loop forever                                                   |20
|         n = rexx tis.read                                            |21
|         if n = -1 then leave     -- there are no more bytes in tis   |22
|         if n = 10 then                                               |23
|           do                                                         |24
|             say line                                                 |25
|             line = ''                                                |26
|             iterate                                                  |27
|           end                                                        |28
|         line = line||n.d2c()                                         |29
|       end                                                            |30
|       tis.close()                                                    |31
|     catch err = exception                                            |32
|       say 'ERROR:' err                                               |33
|       rcset(3)                                                       |34
|     end                                                              |35
|                                                                      |36
+----------------------------------------------------------------------+
                                                    xftp.nrx(Method:xls)
Download the complete source for the xftp.nrx library

Another function (which is NOT in the standard FTP clients) is the xmore

 
+----------------------------------------------------------------------+
| -- method......: xmore                                               |37
| -- purpose.....: type the file on terminal                           |38
| --                                                                   |39
|   method xmore(fid=Rexx) public                                      |40
|     rcclear()                                                        |41
|     nlin = 1                                                         |42
|     do                                                               |43
|       tis = host.get(fid)                                            |44
|       line = ''                                                      |45
|       loop forever                                                   |46
|         n = rexx tis.read                                            |47
|         if n = -1 then leave     -- there are no more bytes in tis   |48
|         if n = 10 then                                               |49
|           do                                                         |50
|             say line                                                 |51
|             line = ''                                                |52
|             nlin = nlin+1                                            |53
|             if nlin > pagesize then                                  |54
|               do                                                     |55
|                 nlin = 1                                             |56
|                 say '+++ (ENTER to continue; Q to quit) \-'          |57
|                 if ask = 'Q' then                                    |58
|                   do                                                 |59
|                     leave                                            |60
|                   end                                                |61
|               end                                                    |62
|             iterate                                                  |63
|           end                                                        |64
|         line = line||n.d2c()                                         |65
|       end                                                            |66
|     catch err = exception                                            |67
|       say 'ERROR:' err                                               |68
|       rcset(5)                                                       |69
|     end                                                              |70
|                                                                      |71
+----------------------------------------------------------------------+
                                                  xftp.nrx(Method:xmore)
Download the complete source for the xftp.nrx library

A small program using the xftp class

As an example of usage of the xftp class, look at the following program:

 
+----------------------------------------------------------------------+
| -- xftp1.nrx                                                         |01
| --   this program just lists the files from a anonymous server       |02
| --   and fetches a big one.                                          |03
| --                                                                   |04
| h = xftp('asisftp.cern.ch')                                          |05
| h.exec('user anonymous toto@test.cern.ch')                          |06
| h.exec('ls')                                                         |07
| h.exec('replace Y')                                                  |08
| h.exec('get README.cernlib')                                         |09
| h.exec('get toto')                                                   |10
| say h.rc                                                             |11
| say h.globrc                                                         |12
| exit                                                                 |13
+----------------------------------------------------------------------+
                                                               xftp1.nrx
Download the source for the xftp1.nrx example

Writing a trivial NNTP client.

The NNTP protocol is described by RFC 977 The NNTP specifies a protocol for the distribution, inquiry, retrieval, and posting of news articles using a reliable stream-based transmission of news among the ARPA-Internet community. NNTP is designed so that news articles are stored in a central database allowing a subscriber to select only those items he wishes to read. Indexing, cross-referencing, and expiration of aged messages are also provided.

We will implement a TRIVIAL NNTP client, using the xsock.nrx library. Our program nnt does allow the reading of a news article and the list of the available ones.

 
+----------------------------------------------------------------------+
| -- trivial NNTP client                                               |01
| --                                                                   |02
| parse arg group article .                                            |03
|                                                                      |04
| -- trivial checks                                                    |05
| --                                                                   |06
| if group = '' then                                                   |07
|   do                                                                 |08
|     say 'Please enter a group. (like "comp.lang.rexx").'             |09
|     exit 1                                                           |10
|   end                                                                |11
|                                                                      |12
| -- connect and get the greating message                              |13
| --                                                                   |14
| node = 'news.cern.ch'     -- change this with your local news server |15
| so = xsock(node,'NNTP')                                              |16
| so.readline()                                                        |17
|                                                                      |18
| -- select the right group                                            |19
| -- and check it's existence                                          |20
| --                                                                   |21
| so.send('group' group)                                               |22
| nn = so.readline()                                                   |23
| parse nn rc . first last .                                           |24
| if rc <> 211 then                                                    |25
|   do                                                                 |26
|     say 'Sorry but group "'group'" is not active.'                   |27
|     exit 3                                                           |28
|   end                                                                |29
|                                                                      |30
| -- OK, now we can                                                    |31
| -- - get all the headers                                             |32
| -- - get the article body                                            |33
| if article = ''                                                      |34
|   then cmd = 'xhdr subject' first'-'last                             |35
|   else cmd = 'article' article                                       |36
| so.send(cmd)                                                         |37
| nn = so.readline()                                                   |38
| parse nn rc .                                                        |39
| if rc > 240 then                                                     |40
|   do                                                                 |41
|     say 'Sorry, but article "'group':'article'" is not available.'   |42
|     exit 4                                                           |43
|   end                                                                |44
|                                                                      |45
| so.receive(",")                                                    |46
|                                                                      |47
| -- that's all                                                        |48
| --                                                                   |49
| so.close()                                                           |50
|                                                                      |51
| exit 0                                                               |52
+----------------------------------------------------------------------+
                                                                 nnt.nrx
Download the source for the nnt.nrx example
 
....................................................................
rsl3pm1 (68) java nnt comp.lang.rexx
19083 rexx under DOS?
19084 Re: Program Priority in REXX or C - How Set?
19085 Suggestions on how to keep a "table" OUTSIDE of Rexx?
19086 Re: Suggestions on how to keep a "table" OUTSIDE of Rexx?
(...)

rsl3pm1 (69) java nnt comp.lang.rexx 20132
From: Dave 
Newsgroups: comp.os.os2.setup.misc,comp.lang.rexx
Subject: Lost rxFTP
(...)
I re-installed OS/2 this weekend and now rxFTP doesn't work.When I try
(...)

....................................................................

Executing NNTP commands interactively

Some small modifications to the above program will allow you to execute commands in an interactive way, in a line mode like shell.

Once you started the command with java nntp1, just type help and the server will answer with the available commands.

 
+----------------------------------------------------------------------+
| -- simple INTERACTIVE                                                |01
| -- news client                                                       |02
| --                                                                   |03
| node = 'news.cern.ch'  -- change it to your local news server        |04
|                                                                      |05
| -- connect to the NEWS server                                        |06
| --                                                                   |07
| so = xsock(node,'NNTP')                                              |08
| parse so.readline() . welcome 'ready'                                |09
| say welcome                                                          |10
|                                                                      |11
| -- wait for commands                                                 |12
| --                                                                   |13
| onelineansw = 'next group'                                           |14
| i = 1                                                                |15
| loop forever                                                         |16
|   say 'NNTP@'node' ['i'] > \-'                                      |17
|   i = i+1                                                            |18
|   cmd = ask                                                          |19
|   if cmd = 'quit' | cmd = 'exit' then leave                          |20
|   so.send(cmd)                                                       |21
|   line = so.readline()                                               |22
|   say line                                                           |23
|   parse cmd cmd rest                                                 |24
|   if onelineansw.wordpos(cmd) <> 0 then iterate                      |25
|   parse line cc rest                                                 |26
|   if cc > 300 then                                                   |27
|     do                                                               |28
|       iterate                                                        |29
|     end                                                              |30
|   so.receive(",")                                                  |31
| end                                                                  |32
|                                                                      |33
| -- we're done                                                        |34
| --                                                                   |35
| so.close()                                                           |36
| say 'Bye.'                                                           |37
| exit                                                                 |38
+----------------------------------------------------------------------+
                                                                nnt1.nrx
Download the source for the nnt1.nrx example

Writing a trivial IMAP client.

RFC 1064 describes the IMAP protocol. IMAP stands for Interactive Mail Access Protocol. The idea is that your mail messages are stored into a server. Your client connects to the server, so you can read your mail using a PC, a UNIX workstation, a MAC or whatever without storing the messages locally.

The protocol is a bit more complicate than the above ones: all messages must be prefixed by a TAG that identify the command. The TAG is in the format "ANNN".

 
client                         server
------                         ------

A001 command1 -------------->
                               Answer
                               (...)
              <--------------  A001 status1

A002 command2 -------------->
                               Answer
                               (...)
              <--------------  A002 status2

 

The small program that follows implements (again) a trivial IMAP client. You need to change the mail.cern.ch address with the address of the IMAP server of your Organization.

 
+----------------------------------------------------------------------+
| -- simple INTERACTIVE                                                |01
| -- news client                                                       |02
| --                                                                   |03
| node = 'mail.cern.ch'  -- change it to your local news server        |04
|                                                                      |05
| -- connect to the NEWS server                                        |06
| --                                                                   |07
| so = xsock(node,'IMAP')                                              |08
| say so.readline()                                                    |09
|                                                                      |10
| -- wait for commands                                                 |11
| --                                                                   |12
| i = 1                                                                |13
| loop forever                                                         |14
|   say 'IMAP@'node' ['i'] > \-'                                      |15
|   i = i+1                                                            |16
|   cmd = ask                                                          |17
|   if cmd = 'help' then                                               |18
|     do                                                               |19
|       say 'LOGIN userid passwd'                                      |20
|       say 'SELECT mailbox        (ex. SELECT INBOX)'                 |21
|       say 'LOGOUT'                                                   |22
|       say 'FETCH sequence data   (ex. FETCH 1 RFC822)'               |23
|       say 'see RFC1064'                                              |24
|       iterate                                                        |25
|     end                                                              |26
|   tag = 'A'||i.right(3,'0')                                          |27
|   so.send(tag cmd)                                                   |28
|   loop forever                                                       |29
|     line = so.readline()                                             |30
|     say line                                                         |31
|     parse line atag .                                                |32
|     if tag = atag then leave                                         |33
|   end                                                                |34
|   if cmd = 'logout' then leave                                       |35
| end                                                                  |36
|                                                                      |37
| -- we're done                                                        |38
| --                                                                   |39
| so.close()                                                           |40
| say 'Bye.'                                                           |41
| exit                                                                 |42
+----------------------------------------------------------------------+
                                                               imapt.nrx
Download the source for the imapt.nrx example

URLs and WEB pages

The basic concepts

The URL

The URL identifies uniquely a document on the Network.

URL is an acronym. It stands for Uniform Resource Locator; it is the address (or if you prefer, the reference) of an Internet resource, usually an HTML document.

You probably saw thousands of URLs when "surfing" the Network, in the form of:

 
  http://java.sun.com/javastation/jstn.html
 

In this URL, like in all other URLs, we can identify 4 basic components, which are:

 

  http://java.sun.com:80/javastation/jstn.html
  ----   ------------ -- ---------------------
   |           |       |         |
   |           |       |         +------------> filename
   |           |       |                        (pathname of the file
   |           |       |                         on the server machine)
   |           |       |
   |           |       +---------------> port number
   |           |                         (default is 80, so you
   |           |                          can happily ommit :80
   |           |                          here shown for educational
   |           |                          purposes)
   |           |
   |           +-----------------> host name
   |                               (the name of the machine
   |                                where the document is located)
   |
   +----------------------> protocol identifier
                            (can be HTTP,
                                    FTP
                                    News
                                    Gopher
                                    File  - for local files)

 

The HTTP daemon

The most common type of WEB documents are handled by HTTP daemons. Those daemons are waiting (usually) on port 80, and accept an handfull of commands.

The most common command is GET followed by a path name. The daemon will answer sending back to the client the selected document.

 
  +----------+
  |          |
  | HTTP     |                          
  | daemon   |---------+
  |          | PORT 80 |    <--------   GET Welcome.html
  +----------+---------+

      (sends                -------->
       Welcome.html)

 

Retriving WEB documents, the basic code.

As we saw, the HTTP protocol used by the HTTP daemons is something very similar to the protocols we already examined for the various socket daemons we encountered so far.

We can write a small program to retrieve a WEB page, using pure sockets:

 
+----------------------------------------------------------------------+
| -- REALLY primitive HTTP client                                      |01
| -- use basic sockets                                                 |02
| --                                                                   |03
| class w3dmp public                                                   |04
|   properties constant                                                |05
|     DEFAULT_PORT    = int 80;                                        |06
|                                                                      |07
|   method usage public static                                         |08
|     say "Usage:   java w3dmp URL"                                    |09
|     say "Example: java w3dmp http://wwwcn.cern.ch/Welcome.html"     |10
|     exit 1                                                           |11
|                                                                      |12
|   method main(args=String[]) public static                           |13
|     -- Get the arguments                                             |14
|     argsl = Rexx(args)                                               |15
|     if argsl = '' then                                               |16
|       do                                                             |17
|         usage()                                                      |18
|       end                                                            |19
|                                                                      |20
|     -- get the URL components                                        |21
|     -- very easy with PARSE                                          |22
|     parse argsl protocol'://'node'/'document                         |23
|     parse node node':'port                                           |24
|                                                                      |25
|     -- basic checks                                                  |26
|     if protocol <> 'http' then                                       |27
|       do                                                             |28
|         say 'Only HTTP protocol, please.'                            |29
|         exit 1                                                       |30
|       end                                                            |31
|     if node = '' then                                                |32
|       do                                                             |33
|         say 'Missing server name.'                                   |34
|         exit 2                                                       |35
|       end                                                            |36
|     if port = '' then port = DEFAULT_PORT                            |37
|                                                                      |38
|     -- do the real job                                               |39
|     s = Socket null;                                                 |40
|     do                                                               |41
|       s    = Socket(node,port);                                      |42
|       sin  = DataInputStream(s.getInputStream());                    |43
|       sout = PrintStream(s.getOutputStream());                       |44
|                                                                      |45
|       cmd  = 'GET' '/'||document                                     |46
|       sout.println(cmd)                                              |47
|       line = String                                                  |48
|       loop forever                                                   |49
|         -- Read a line from the server.                              |50
|         line = sin.readLine();                                       |51
|         -- Check if connection is closed (i.e. for EOF)              |52
|         if (line = null) then leave                                  |53
|         -- And write the line to the console.                        |54
|         Say line                                                     |55
|       end                                                            |56
|     catch e1=IOException                                             |57
|       System.err.println(e1)                                         |58
|     finally                                                          |59
|       do                                                             |60
|         if (s \= null) then s.close()                                |61
|       catch e2=IOException                                           |62
|        e2=e2                                                         |63
|       end                                                            |64
|   end                                                                |65
|                                                                      |66
| exit 0                                                               |67
+----------------------------------------------------------------------+
                                                               w3dmp.nrx
Download the source for the w3dmp.nrx example

The parsing of the URL components is done (of course) with two parse instructions, in order to correctly extract the (optional) port number, in case it is different from 80.

The code can be made even shorter, using the already discussed xsock library functions.

 
+----------------------------------------------------------------------+
| -- REALLY primitive HTTP client                                      |01
| -- use basic sockets (and xsock library)                             |02
|                                                                      |03
| -- Get the arguments                                                 |04
| if arg = '' then                                                     |05
|   do                                                                 |06
|     say "Usage:   java w3dmp URL"                                    |07
|     say "Example: java w3dmp http://wwwcn.cern.ch/Welcome.html"     |08
|     exit 1                                                           |09
|   end                                                                |10
|                                                                      |11
| -- get the URL components                                            |12
| -- very easy with PARSE                                              |13
| parse arg protocol'://'node'/'document                               |14
| parse node node':'port                                               |15
|                                                                      |16
| -- basic checks                                                      |17
| if protocol <> 'http' then                                           |18
|   do                                                                 |19
|     say 'Only HTTP protocol, please.'                                |20
|     exit 2                                                           |21
|   end                                                                |22
| if node = '' then                                                    |23
|   do                                                                 |24
|     say 'Missing server name.'                                       |25
|     exit 3                                                           |26
|   end                                                                |27
| if port = '' then port = 'HTTP'                                      |28
|                                                                      |29
| -- do the real job                                                   |30
| so = xsock(node,'HTTP')                                              |31
| so.send('GET /'document)                                             |32
| so.receive()                                                         |33
| so.close()                                                           |34
|                                                                      |35
| exit 0                                                               |36
+----------------------------------------------------------------------+
                                                              w3dmp1.nrx
Download the source for the w3dmp1.nrx example
 
 *** This section is: 
  
 *** and will be available in next releases

Summary

Let's resume what we saw in this chapter.


File: nr_15.html.

The contents of this WEB page are Copyright © 1997 by Pierantonio Marchesini / ETH Zurich.

Last update was done on 18 May 1998 21:47:51(GMT +2).