SDSU CS 580 Client-Server
Spring Semester, 2004
Streamless Sockets
Previous    Lecture Notes Index    Next    
© 2004, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 06-Apr-04

References

Java On-line API http://java.sun.com/j2se/1.4.1/docs/api/

VisualWorks Internet Client Developer's Guide, Socket Programming Chapter 2, docs/NetClientDevGuide.pdf in VW 7 distribution


NIO On-line Examples http://java.sun.com/j2se/1.4/docs/guide/nio/example/index.html

Martin Kobetic, private communications



Doc 23, Streamless Sockets Slide # 2

Streamless Socket Access


Both VisualWorks and Java (JDK 1.4) support

Reading/writing on sockets without streams

Provides access to more socket functionality



Doc 23, Streamless Sockets Slide # 3

VisualWorks


Supports two versions:


Read/Write

Works for TPC only

Slightly simpler than send/receive

Exceptions raised differ on Window & UNIX



Send/Receive

Works with UDP & TCP

Doc 23, Streamless Sockets Slide # 4
Waiting for Data

SocketAccessor supports:




  • Return true if a time out occurred

  • Same as read versions but used on writing data


Send/Receive always requires the use of these waits

Read/Write sometimes works without them

So always use them

Doc 23, Streamless Sockets Slide # 5
Read/Write

Example – From Date Server


processRequest: aSocketAccessor 
   | timedOut readBuffer charactersRead date |
   
   [timedOut := aSocketAccessor readWaitWithTimeoutMs: 10000.
   timedOut ifTrue: [^nil].
   readBuffer := String new: 50.
   charactersRead := aSocketAccessor readInto: readBuffer
            untilFalse: [:count | count < 5].
   (readBuffer startsWith: 'date') 
      ifTrue: 
         [aSocketAccessor writeWait.
         date := Date today printString.
         aSocketAccessor writeFrom: date]] 
         ensure: [aSocketAccessor close]


Doc 23, Streamless Sockets Slide # 6
Basic Operation

Before read/write call wait operation ready

In both read & write only part of the data may be processed!

Read/write methods return the number of bytes processed

You code has to make sure all data is processed


Doc 23, Streamless Sockets Slide # 7
Read/Write operations

readInto: aBuffer
readInto: aBuffer startingAt: index for: count
readInto: aBuffer untilFalse: aBlock

writeAll: aBuffer
writeFrom: aBuffer
writeFrom: aBuffer startingAt: index for: count
writeFrom: aBuffer startingAt: index forSure: count
writeFrom: aBuffer startingAt: index for: count untilFalse: aBlock

See Internet Client Developer’s Guide Chapter 2 for details

Doc 23, Streamless Sockets Slide # 8

Testing


How to test processRequest: aSocketAccessor ?

Build a mock SocketAccessor

Implement the read/write/wait methods

Read methods read from stream on a String

Write methods write to a write stream on a String

Provide methods to access data written to the mock object


Doc 23, Streamless Sockets Slide # 9
Waiting for Data & Streams

One can do a readWait with streams

processWithStreamsRequest: aSocketAccessor 
   | clientRequest aReadStream aWriteStream |
   
   [aReadStream := aSocketAccessor readStream lineEndTransparent.
   aWriteStream := aSocketAccessor writeStream lineEndTransparent.
   (aSocketAccessor readWaitWithTimeoutMs: 10000) ifTrue: [^nil].
   clientRequest := aReadStream through: Character cr.
   (clientRequest startsWith: 'date') 
      ifTrue: 
         [aWriteStream
            nextPutAll: Date today printString;
            commit]] 
         ensure: [aSocketAccessor close]

One wants to use

 aReadStream basicAtEnd not or: 
   [ (aSocketAccessor readWaitWithTimeoutMs: timeout) not ]

before reading

Doc 23, Streamless Sockets Slide # 10

Java JDK 1.4 NIO & Sockets


JDK 1.4 has streamless access to sockets

Important new classes


New packages



Doc 23, Streamless Sockets Slide # 11
Channels

Two-way connection to an IO device
Has


Supports



Doc 23, Streamless Sockets Slide # 12
Buffers


Channels read/write into buffers

Buffer class for each primitive data type

Byte, int, float, char, double, long, short


Encoders & Decoders

Maps Unicode strings to/from bytes


Doc 23, Streamless Sockets Slide # 13

Date Server Example

import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.util.*;
public class NIOTimeServer 
   {
   ServerSocketChannel acceptor;
    private static Charset usAscii = Charset.forName("US-ASCII");
    private static CharsetDecoder asciiDecoder = usAscii.newDecoder();
    private static CharsetEncoder asciiEncoder = usAscii.newEncoder();
   
   public static void main(String[] args) throws IOException {
      int port = Integer.parseInt( args[0]);   
      
      NIOTimeServer server = new NIOTimeServer( port );
      server.run();
   }
   
   public NIOTimeServer(int port ) throws IOException {
      InetSocketAddress serverAddress =
         new InetSocketAddress(InetAddress.getLocalHost(), port);
      acceptor = ServerSocketChannel.open();
      acceptor.socket().bind( serverAddress );
   }


Doc 23, Streamless Sockets Slide # 14
Date Server Example Continued

   public void run() 
      {
      while (true) 
         {
         try
            {
            SocketChannel client = acceptor.accept();
            processRequest( client );
            }
         catch (IOException acceptError)
            {
            // for a later lecture
            }
         }
      }
   
   void processRequest( SocketChannel  client) throws IOException
      {
      try
         {
         String request = readLine( client );
         String response = processRequest( request);
         CharBuffer charsOut = CharBuffer.wrap( response + "\r\n");
         ByteBuffer bytesOut = asciiEncoder.encode(charsOut);
         client.write(bytesOut);
         }
      finally  
         {
         client.close();
         }
      }
      

Doc 23, Streamless Sockets Slide # 15
Date Server Example Continued

   String readLine( SocketChannel  client) throws IOException
      {
      ByteBuffer inputBytes = ByteBuffer.allocate(1024);
      String input = "";
      CharBuffer inputChars;
      while (input.lastIndexOf( "\n") < 0 )
         {
         inputBytes.clear();
         client.read( inputBytes );
         inputBytes.flip();
         inputChars = asciiDecoder.decode(inputBytes);
         input = input + inputChars.toString();
         }
      return input;
      }
      
   String processRequest( String request )
      {
      if (request.startsWith("date")) 
         return new Date().toString();
      else
         return "";
      }
   }


Doc 23, Streamless Sockets Slide # 16
Comments

Note the variation of detail in processRequest( SocketChannel client)

Would it be better to have:

      try
         {
         String request = readLine( client );
         String response = processRequest( request);
         write( client, response);
         }

Does it make sense to have so many methods is such a small example?


Doc 23, Streamless Sockets Slide # 17

How do we Test this?







Copyright ©, All rights reserved.
2004 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
OpenContent license defines the copyright on this document.

Previous    visitors since 06-Apr-04    Next