Totally Objects - Socket Set - Version 5.5 [1.0]

Introduction

This document explains how to use the Socket Set product from Totally Objects for IBM's VisualAge for Smalltalk. The product provides tools that enable you to add TCP/IP capabilities to your applications without getting tied down with the complexities of sockets programming. Some high level tools are included to do everyday tasks such as sending and receiving email (SMTP + POP3 with attachments) or uploading and downloading files (FTP).

The most valuable aspect of the product is the ease in which servers can be built. You specify a port to which the server should listen and a block to be executed for each client that connects: the threads are managed for you so the connections appear asynchronous.

Installing the Socket Set

This Totally Objects product has been packaged as three configuration maps. To import them into your library select 'Browse Configuration Maps' from the 'Tools' menu of the 'System Transcript'. In the 'Configuration Maps Browser' select 'Import...' from the 'Names' menu and select the file tobss5-5_1-0-*.dat. You should then select the three configuration maps contained within this file:

To load the configuration maps into your image select each of them in the 'Configuration Maps Browser' select 'Load With Required Maps' from the 'Editions' menu. You must first, however, load the application 'SocketCommunicationsInterface' (and its prerequisites) - these are part of VAST.

If you are using the Parts interface to Socket Set you will need to copy the directory 'tobsock' (which contains icons) into your root VAST directory.

General Classes

Most of the tools in the Socket Set require you to send and receive messages to other hosts using TCP/IP. To specify these hosts you need to use the TobSocketsHost class. There are seven ways to instantiate the class; examples are given below:

You then need to specify the address (comprising a host and port number) you wish to connect to. You use the TobSocketsAddress class to do this. For example:

The client side to the TCP/IP protocols in the Socket Set are subclasses of TobSocketsProtocol. These subclasses can be instantiated using #new or #statusStream: (which requires a WriteStream as input to which status messages would be put).

Sending Mail Using SMTP

To send mail you must first create an instance of the class TobSocketsSMTPMailMessage. The following methods are define in TobSocketsSMTPMailMessage to let you specify information about the message:

Method

Description

sendersEmailAddress:

The email address of the sender (a String)

sendersName:

The name of the sender (a String)

subject:

The subject of the message (a String)

messageText:

The contents of the message itself (a String - 7bit ASCII)

To specify the recipients (or recipients of copies) use these methods:

Method

Description

addRecipient:

Adds a recipient (a TobSocketsMailRecipient)

addRecipient:emailAddress:

Adds a recipient using name and email address (both Strings)

addCopyRecipient:

Adds a recipient of a copy (a TobSocketsMailRecipient)

addCopyRecipient:emailAddress:

Adds a recipient of a copy using name and email address (both Strings)

addBlindCopyRecipient:

Adds a recipient of a blind copy (a TobSocketsMailRecipient).

addBlindCopyRecipient:emailAddress:

Adds a recipient of a blind copy using name and email address (both Strings)

To send the message use TobSocketsSMTP>>#mail:address: giving the message and the address as arguments.

For example:

To send any items in the header of the message (in addition to those automatically created) use TobSocketsSMTPMailMessage>>#extraHeaderItems: and give it a Dictionary where the keys are the header item names (e.g. 'DigitalCertificate:') and the values are the header item values.

To find out how successful the sending was (assuming no error occurs) you can send the resulting TobSocketsSMTP object the message #statusOfRecipients. This will answer a Dictionary with the recipients (or recipients of copies) as keys and TobSocketsSMTPRecipientStatus objects as values.

To add attachments use these methods (in TobSocketsSMTPMailMessage):

Method

Description

attachTextStream:name:

Expects a ReadStream and String as arguments. The contents of the stream will be attached as a text (7-bit ASCII) and assigned the given name.

attachApplicationDataStream:name:applicationName:

Expects a ReadStream and Strings as arguments. The contents of the stream will be attached as binary (encoded using base64) and assigned the given name. The application name corresponds to a registered MIME application that should be used by the client to open the attachment.

addAttachment:

This should be used when the above methods do not provide the flexibility you require. The argument is an instance of TobSocketsSMTPAttachment (described below).

TobSocketsSMTPAttachments have four basic attributes: The contents, the encoding to be used, the type and the subtype. The Internet Request For Comments 1341 should be consulted for a definitive explanation of the acceptable values. The following methods should be used to set these attributes:

Method

Description

type:

Requires a String. Valid values are 'application', 'audio', 'image', 'message', 'multipart', 'text', 'video' or any String prefixed with 'x-'.

subType:

Requires a String. Valid values depend on the 'type' specified.

applicationType:

Sets the type to 'application' and the subType to the argument provided.

audioType:

Sets the type to 'audio' and the subType to the argument provided.

imageType:

Sets the type to 'image' and the subType to the argument provided.

messageType

Sets the type to 'message' and the subType to 'rfc822' (the only valid subType for thetype).

multipartType

Sets the type to 'multipart' and the subType to 'mixed'.

textType:

Sets the type to 'text' and the subType to the argument provided ('plain' or 'richtext').

videoType:

Sets the type to 'video' and the subType to the argument provided.

content:encoding:

Sets the content of the attachment (a String). The second argument specifies which encoding has been applied to the content (not the encoding to be applied). Valid encodings are 'BASE64', 'QUOTED-PRINTABLE', '8BIT', '7BIT', 'BINARY' or a String prepended with 'X-'. For ASCII text '7BIT' should be used.

base64EncodeContent:

Sets the content of the attachment (a String) and specifies that base64 encoding should be applied. This is ideal for sending binaries.

quotedPrintableEncodeContent:

Sets the content of the attachment (a String) and specifies that Quoted-Printable encoding should be applied. This is ideal for formatted text.

rawContent:

Sets the content of the attachment (a String) and specifies that it should not be encoded. This is ideal for 7-bit ASCII.

The following code snippet shows how you might send a binary executable and some binary application data as attachments.

Notice that the above code uses an alternative way to send email (by creating the message and using the method #mail:).

Downloading Mail Using POP3

To use the POP3 protocol to access a mailbox an instance of TobSocketsPOP3 should be created and then configured using the methods:

Then the following methods can be used

So to download all messages from the server and delete them (so they are not downloaded again next time) the code would look something like this:

The answer to the above message will be an OrderedCollection of objects of the class TobSocketsPOP3MailMessage. These objects understand the following methods:

Method

Description

headedItems

Gets an EsOrderedDictionary of the items in the messages header.

messageText

Gets a 7-bit ASCII String - the body of the message.

decodedMessage

Gets the body of the message as a String after the appropriate decoding algorithm has been applied.

attachments

Gets an OrderedCollection of TobSocketsPOP3Attachments (described below).

addXDecoder:name:

Specifies a decoding object (i.e. one that understands #decode: - taking a String and answering the decoded String) to be used for attachments that have an transfer encoding type corresponding to the second argument. These transfer encoding types must be prefixed with 'X-'.

An incoming mail with attachments will answer an OrderedCollection of TobSocketsPOP3Attachments when sent the message #attachments. These objects understand the following methods:

Method

Description

content

Gets the raw undecoded attachment content (a String).

contentTransferEncoding

Gets the name of the transfer encoding used (a String).

type

Gets the type of attachment (a String).

contentTransferEncoding

Gets the subType of attachment (a String).

decodedContent

Gets the content of the attachment after applying the appropriate decoding algorithm.

headerItems

Gets an EsOrderedDictionary of the items in the attachment's header.

Uploading And Downloading Files Using FTP

The method TobSocketsFTP>>#downloadFile:address:username:password:account:type:stream: has been provided for downloading files. It can be used as follows:

Similarly the method TobSocketsFTP>>#uploadFile:address:username:password:account:type:stream: has been provided for uploading files to servers. Two additional uploading methods can also be used. TobSocketsFTP>>#uploadAppendFile:address:username:password:account:type:stream: appends the contents of the stream onto the file on the server (or creates a new file if one does not already exist). TobSocketsFTP>>#uploadUniqueFile:address:username:password:account:type:stream: will use a different file name (chosen by the server) if the file already exists on the server.

Deleting or renaming files can be done with TobSocketsFTP>>#deleteFile:address:username:password:account: and TobSocketsFTP>>#renameFile:to:address:username:password:account:. For example:

To handle stalling during data transfer you can set the #stallTimeOut value of the TobSocketsFTP object. Whenever there is inactivity for a period either ExTobSocketsReceiveTimedOut or ExTobSocketsSendTimedOut will be signalled.

The default value is got from the class method defaultStallTimeOut which is initially 0 (i.e. ignore time-outs).

You can also download files using FTP by creating a URL. To create the URL object you can do either:

Or,

The resulting object (an instance of TobSocketsFTPURL) can be sent any of the following messages to download a file:

The first argument of each is the stream to which you want the file's content written. The emailAddress argument is a String that will be used as a password for anonymous FTP. The statusStream is a stream to which status information will be sent. Such URL should have the form (See RFC 1738 for a full description):

So to download the file given in the earlier example:

TCP/IP Clients

If you wish to use the Socket Set to implement the client end of your TCP/IP protocols then you have two options:

An example of option (2) is given below.

Say you have a TCP server (listening on port 9000) that will reverse the order of strings that you send it and responds with appropriate messages upon success or failure. The code might look something like this:

Methods in the TobSocketsSocket class that are of general use:

Method

Description

connect:

Takes a TobSocketsAddress as an argument. If the connecting process takes longer than the value #connectTimeOut then the exception ExTobSocketsConnectTimedOut will be signalled.

connectTimeOut:

Sets the number of milliseconds after which a time-out will occur when using #connect:. Using the value 0 means 'No time-out'.

connectLoopBlock:

Sets a two argument Block (or nil) that will get executed repeatedly (using #value:value) while trying to connect (using #connect:). If the connection happens immediately or an error occurs the block may not be executed at all. The arguments sent to the block will be:

  • first: self (i.e. the TobSocketsSocket)
  • second: the TobSocketsAddress to which it is trying to connect.

    The block should answer a Boolean. If 'false' then the connection will terminate with the exception ExTobSocketsConnectAborted.

    This facility is useful if you need to execute any code while trying to connect to a server (e.g. allowing a user to press a 'Cancel' button, animating a graphic, or allowing a user to abort a connection when there is no time-out).

  •    

    lineDelimiter:

    Set the String to use as a line delimiter for the #cr and #nextLine methods (default value is <CR><LF>)

    receiveStrings

    Collections received from the socket will be expressed as Strings.

    receiveByteArrays

    Collections received from the socket will be expressed as ByteArrays.

       

    peek:

    Peeks the specified number of characters from the socket. The answered collection may be shorter than the specified length if insufficient characters are ready to be peeked. If the peeking takes longer than the value #receiveTimeOut then the exception ExTobSocketsReceiveTimedOut will be signalled.

    peekExactly:

    The same as #peek: except the method will wait until there are sufficient characters to peek (but may still time-out).

    peek

    Peeks one Character or byte (depending whether the socket has been set to receive Strings or ByteArray) from the socket.

    peekNoTimeOut:

    The same as #peek: but ignores the time-out.

    peekNoTimeOut

    self peekNoTimeOut: 1

    next:

    Receives the specified number of characters from the socket. The String answered may be shorter than the specified length if insufficient characters are ready to be received.

    nextExactly:

    The same as #next: except the method will wait until there are sufficient characters to receive.

    next

    Receives one Character or Byte (depending whether the socket has been set to receive Strings or ByteArray) from the socket.

    nextNoTimeOut:

    The same as #next: but ignores the time-out.

    nextNoTimeOut

    self nextNoTimeOut: 1

    nextDatagram:

    Answers an instance of TobSocketsDatagram (must be a UDP socket). The argument indicates the size of the buffer to use for the data within the datagram. Use the #truncated method to see if the data within the datagram has been truncated.

    nextDatagramNoTimeOut:

    The same as #nextDatagram: but ignores the time-out.

    receiveTimeOut:

    Sets the number of milliseconds after which a time-out will occur when using some of the above methods. Using the value 0 means 'No time-out'.

       

    upTo:

    Receives up to the next occurance of the specified Character or byte and answers a collection of the received items (not including the value in the argument). If the receiving takes longer than the value #upToTimeOut then the exception ExTobSocketsUpToTimedOut will be signalled.

    upToNoTimeOut:

    The same as #upTo: but ignores the time-out.

    upToAll:

    The same as #upTo: except the receiving is up to the specified String or ByteArray.

    upToAllNoTimeOut:

    The same as #upToAll: but ignores the time-out.

    nextLine:

    Receives up to the lineDelimiter.

    nextLineNoTimeOut:

    Receives up to the lineDelimiter but ignores the time-out.

    upToTimeOut:

    Sets the number of milliseconds after which a time-out will occur when using some of the above methods. Using the value 0 means 'No time-out'.

       

    nextPutAll:

    Sends the specified String or ByteArray. If the sending takes longer than the value #sendTimeOut then the exception ExTobSocketsSendTimedOut will be signalled.

    nextPutAllNoTimeOut:

    The same as #nextPutAll: but ignores the time-out.

    nextPut:

    Sends the specified byte or Character. If the sending takes longer than the value #sendTimeOut then the exception ExTobSocketsSendTimedOut will be signalled.

    nextPutNoTimeOut:

    The same as #nextPut: but ignores the time-out.

    cr

    Sends the collection answered by the message #lineDelimiter.

    tab

    Sends a tab character (ASCII 9)

    space

    Sends a space character (ASCII 32)

    sendDatagram:to:

    Sends the data in argument one (a TobSocketsDatagram) to the address specified in the second argument. It answers the number of bytes of the data sent. Use the #truncated method to see if the data within the datagram had to be truncated before sending.

    sendDatagramNoTimeOut:to:

    The same as #sendDatagram:to: but ignores the time-out.

    sendTimeOut:

    Sets the number of milliseconds after which a time-out will occur when using some of the above methods. Using the value 0 means 'No time-out'.

    Time-outs: Notice that there are four types of time-out:

    TCP/IP Servers

    Creating TCP/IP servers can be a more complicated than clients, so the Socket Set provides you with the utility class TobSocketsServer (and its subclasses TobSocketsDatagramServer and TobSocketsStreamServer) to do the work for you.

    To create a server you simply use the class method #address:clientBlock:.

    The first argument is the address that you want to listen on and the second is a single argument block where the argument is the socket to a client that connects.

    This example creates server corresponding to the client example above.

    To try out the above code execute it, open a terminal application (Select 'Run...' from the 'Start' menu and type 'telnet' to get the application that comes with Windows 95 or NT). Connect to your machine on port 9000. You should see the prompt 'OK'. Next type 'REVERSE some text' (you may not be able to see what you are typing) and press 'Enter'. Then you should then see 'BAD REQUEST' (if you made a typo) or 'OK txet emos'. The connection will then be closed.

    To stop the server execute:

    Alternatively, the server will automatically be stopped if the process in which it runs is terminated using the debugger. Note that the name of the process includes the address and port number for easy identification.

    Most of the time you will find that this simple approach to servers does everything you need, but there are a few more methods that you may find useful:

    Method

    Description

    childSockets

    Answers a collection of child sockets (TobSocketsChildSocket) relating to the current connections.

    forkChildren:,

    forkChildren

    Sets and gets whether the process should fork (with the same priority as the server) whenever a client connects. If this value is false then a second child can not connect until the first execution of the clientBlock has completed. The default value is true.

    isRunning

    Answers true if the server is waiting for clients to connect.

    killChildren

    Closes all connected sockets.

    loopBlock:

    A two-argument block that is executed every time the listening socket loops waiting for a client to connect. The first argument is the server itself and the second is the server's listening socket. The loopBlock can also be specified using the class method #address:clientBlock:loopBlock: instead of #address:clientBlock:.

    numberOfChildren

    Answers the number of children currently connected.

    numberOfConnections

    Same as #numberOfChildren (for compatibility).

    start

    Starts the server without forking the process.

    Note About Process Management

    Your servers will usually need to manage many simultaneous connections from clients. If this is the case the server should be configured to fork child connections (the default setting); that is, create a new process for each connection. The server object will automatically manage the resumption of these child processes to simulate asynchronous behaviour. If, however, you do not wish the server object to automatically resume the child process (say, to delay or wait on a semaphore) then the message #resumedByServer: can be sent to the process with argument false. Alternatively the method #notResumedByServerDuring: can be used. For example:

    UDP Clients

    If you wish to use UDP instead of TCP (to send datagrams to a server) then the process is simpler. You first create the socket using #newDatagram, create a new TobSocketsDatagram and then send it using the #sendDatagram:to: message. For example:

    UDP Servers

    Creating a UDP server is very similar to creating a TCP server. The main difference being that the argument to the client block is the incoming datagram. For example:

    To specify the maximum size of the data of incoming datagrams send the server the message #bufferSize:. Any data larger than this value will be truncated and the 'truncated' flag set to true. The message #timeOut can be sent to the server. This specifies the period of the time the server should be prepared to wait when no datagrams are being sent to it. If the period is exceeded then an ExTobSocketsReceiveTimedOut exception is signalled. Setting the value to 0 (the default value) means that the server will not time out.

    The incoming datagram understands three special messages:

    Method

    Description

    data

    Answers the data put into the datagram by the sender (a String or ByteArray).

    sender

    The address of the sender.

    truncated

    A Boolean value indicating whether the dataString has been truncated.

    To stop the example server execute:

    Alternatively, the server will automatically be stopped if the process in which it runs is terminated using the debugger. Note that the name of the process includes the address and port number for easy identification.

    Socket Set Exceptions

    The exceptions used by the Socket Set are stored within five pool dictionaries; TobSocketsExceptions, TobSocketsFTPExceptions, TobSocketsPOP3Exceptions, TobSocketsSMTPExceptions and TobSocketsURLExceptions.

    A description of each is given below. Indentation denotes the parent-child relationships between exceptions.

    Using Socket Set's Parts

    To use the parts you must first load the configuration map, 'Totally Objects, Socket Set - Parts' into your image.

    A new parts category ('Totally Objects' Socket Set') will be added to the Composition Editor. This category contains ten parts. These are:

    To see examples of these parts in action load the configuration map 'Totally Objects, Socket Set - Parts Examples'. A brief overview of each is given below.

    TobSocketsPartsExamplesFTPClient

    This example lets you upload or download files from FTP servers. Try out the example by downloading a file from the Microsoft site. Enter the values:

    Then press 'Download...' and enter the name of the file you would like to create locally.

    After a short while the file should be downloaded.

    TobSocketsPartsExamplesSMTPMailSender

    This example lets you send internet mail. Typical values to be entered in the window are:

    Similarly TobSocketsPartsExamplesSMTPMailWithAttachment can be used to send internet mail with a simple text attachment.

    TobSocketsPartsExamplesPOP3MailReader

    This example will read the next email message delivered by your POP3 server. Note that the message does not get deleted on the server (to avoid you losing real email while testing). This means that the same message will keep getting downloaded until it is deleted from the server (by, say, downloading the message using your normal mail reader). Typical values to be entered in the window are:

    Further Information