SDSU CS 596 Client-Server Programming
Comments on Grader Protocol

[To Lecture Notes Index]
San Diego State University -- This page last updated April 23, 1996
----------

Contents of Comments on Grader Protocol Lecture

  1. Issues
  2. States
    1. General Comments
      1. Client Command Structure
      2. Server Response Structure
      3. Making Connection
    2. Guest State
      1. Login SubCommands
      2. Get SubCommands
    3. Student State
    4. InstructorState
  3. Possible Implementation
    1. First Pass at Use In Client

Issues

Who Wrote This?

Initially, the server host starts the GR service by listening on TCP port 110. When a client host wishes to make use of the service, it establishes a TCP connection with the server host. When the connection is established, the GR server sends a greeting. The client and GR server then exchange commands and responses (respectively) until the connection is closed or aborted.

Commands in the GR consist of a keyword, possibly followed by one or more arguments. All commands are terminated by a CRLF pair. Keywords and arguments consist of printable ASCII characters. Keywords and arguments are each separated by a single SPACE character. Keywords are three or four characters long. Each argument may be up to 40 characters long.

Responses in the GR consist of a status indicator and a keyword possibly followed by additional information. All responses are terminated by a CRLF pair. There are currently two status indicators: positive ("+OK") and negative ("-ERR").

Myers & Rose

Initially, the server host starts the POP3 service by listening on TCP port 110. When a client host wishes to make use of the service, it establishes a TCP connection with the server host. When the connection is established, the POP3 server sends a greeting. The client and POP3 server then exchange commands and responses (respectively) until the connection is closed or aborted.

Commands in the POP3 consist of a keyword, possibly followed by one or more arguments. All commands are terminated by a CRLF pair. Keywords and arguments consist of printable ASCII characters. Keywords and arguments are each separated by a single SPACE character. Keywords are three or four characters long. Each argument may be up to 40 characters long.

Responses in the POP3 consist of a status indicator and a keyword possibly followed by additional information. All responses are terminated by a CRLF pair. There are currently two status indicators: positive ("+OK") and negative ("-ERR").
Issue

This document follows the structure found in rfc 1725.

1. Introduction
My introduction blah blah blah.


2. Basic Operation
I describe how this works. blah blah blah.

3. Start State
More of my own words.
Command summary
STUDENT name
Arguments:
A string consisting of a last name with no spaces followed by a comma(,) followed by a first name. A space separates the string and the keyword STUDENT
Restrictions:
Some stuff here
Possible Responses:
More stuff
Examples:
C: STUDENT whitney,roger
S: status:success

Issue
Parsing Options

getCourse courseName [year] [semester]

Examples:
getCourse CS596
getCourse CS596 1996
getCourse CS569 spring
getCourse CS596 1996 spring
getCourse CS596 96 spring
getCourse CS596 2000 spring
getCourse CS596 000 spring
getCourse CS596 00 spring
getCourse CS596 0 spring


Solution

getCourse:name=courseName;[year=date];[semester=term]

term := fall|winter|spring|summer
date := four digit representing the calendar year

Examples:
getCourse:name=CS596
getCourse:name=CS596;year=1996
getCourse:name=CS596;semester=spring
getCourse:name=CS596;year=1996;semester=spring
getCourse:name=CS596;semester=spring;year=1996
getCourse:semester=spring;name=CS596;year=1996

Issue
What (Who) am I?

C: USER whitney
S: +OK, password required
C: PASS funtime
S: +OK , In instructor state

Instructors
Dan Whitney, Anthropology
Mark Whitney, Child Development
Roger Whitney, CS
Students
Roger Whitney, Business student

A Solution to Student-Instructor


C: STUDENT whitney
S: +OK, password required
C: PASS funtime
S: +OK , In student state

C: INSTRUCTOR whitney
S: +OK, password required
C: PASS oknow
S: +OK , In instructor state

Issue

C: AddStudents
S: +OK, Ready for data
C: adams, apple
S: +OK, Ready for data
C: bones, dry
S: +OK, Ready for data
C: EOT
S: +OK, Ready for new command

Result

Many states!
Hard to implement
A Solution

C: AddStudents
lastName=adams,firstName=apple
lastName=bones, firstName=dry
EOT
S: +OK, Ready for new command
Issue
Command summary
GetSummary
Arguments:
none
Restrictions:
Can be issued in any state
Possible Responses:
Server returns +OK followed by the summary of the current class

States

Guest (or Start State)
Allows login and guest privileges
Student
Commands allowed after successful login by student
Instructor
Commands allowed after successful login by faculty

SystemAdministrator
Commands allowed after successful login by system administer
Perform tasks like add faculty, change passwords, update database of existing courses, etc.
Beyond the scope of the assignment

Bureaucrat
Commands allowed after successful login by various administration types
Allows EOP tracking of students, etc.
Beyond the scope of the assignment

General Comments


Client Command Structure

command:subcommand<crlf>
attribute1:value1<crlf>
attribute2:value2<crlf>
attributeN:valueN<crlf>
endCommand<crlf>

where:
command:subcommand must be the first line
there may be any number of attributes
the attributes in general can be in any order
endCommand must be the last line

Server Response Structure


status:statusString<crlf>
text:someText<crlf>
singleItem:value1<crlf>
list:item1;item2;itemN<crlf>
labeledList:name1=value1;name2=value2;nameM=valueM
endResponse<crlf>
where statusString ::= success | failure

Making Connection

When the client connects to the server the server response will be:

status:success<crlf>
text:DateAndTime<crlf>
version:versionNumber<crlf>

The DateAndTime can be used server and client to encrypt passwords

Guest State

Commands

login:student
login:instructor

get:listOfDepartments
get:departmentCourses
get:courseSummary

quit:now
Guest State

Login SubCommands

subcommand  =  student
	| instructor

attribute = name
	| password
	| encriptedPassword

Example
Client Command
login:student
name:first=Roger;last=Smith;id=555-55-5555
password:HiMom
endCommand

where password is not encrypted

Server Response
status:success
text:Student record available
endResponse

If failure, the text gives reason for failure and Server drops connection after response.

If success server changes to student state

Get SubCommands

Guest State
subcommand  =  listOfDepartments
	| departmentCourses
	| courseSummary


Client Command
get:listOfDepartments
term:spring
year:1996
endCommand

default values for term and year are current term and year

Server Response
status:success
text:Department names to follow
departments:Math;Computer Science;English
endResponse
where status is either "success" or "failure". If failure no change in server state

Guest State
get:departmentCourses

Client Command
get:departmentCourses
department:Computer Science
endCommand

Server Response
status:success
text:Courses follow
listSize:3
course1:name=CS 596 Client/Server;id=07000;section=1
course2:name=CS 596 MultiMedia;section=2;id=07011
course3:name=CS 662 Parallel Algor;id=07055;section=1
endResponse

or
status:failure
text:No Courses for that department
endResponse


No change in state on either success or failure
Some things one could do
Explicit Default

Server Response
status:success
text:Courses follow
listSize:3
course1:name=CS 596 Client/Server;id=07000
course2:name=CS 596 MultiMedia;section=2;id=07011
course3:name=CS 662 Parallel Algor;id=07055
default:section=1
endResponse

Implicit Default

Server and client code agree on default value
status:success
text:Courses follow
listSize:3
course1:name=CS 596 Client/Server;id=07000
course2:name=CS 596 MultiMedia;section=2;id=07011
course3:name=CS 662 Parallel Algor;id=07055
endResponse

Guest State
get:courseSummary

Client Command
get:courseSummary
couresId:07011
endCommand

Server Response
status:success
text:Summary Follows
gradeEvents:Exam;Syntax Quiz;Server
summaryLabels:Points Possible;Max score;Average
Points Possible:Exam 1=100;Server=10;Syntax Quiz=10
Max score:Exam 1=90;Syntax Quiz=10;Server=10
Average:Exam 1=82;Server=8;Syntax Quiz=2
endResponse

Guest State
quit:now

Client Command
quit:now
endCommand

Server Response
status:success
text:Goodbye
endResponse

Client and server drop connection

Student State

Sample Command - get grades for a student

Client Command
get:grades
coureId:07011
endCommand

Server Response
status:success
text:Grades Follows
gradeEvents:Exam;Syntax Quiz;Server
grades:Exam=12;Syntax Quiz=2;Server=3
endResponse


InstructorState

Sample Command

Client Command
put:newGradeEvent
coureId:07011
gradeEvent:Grader Protocol
summaryInfo:Points Possible;Max score;Average
endCommand

Server Response
status:success
text:Grades Follows
gradeEvents:Exam;Syntax Quiz;Server
grades:Exam=12;Syntax Quiz=2;Server=3
endResponse

Possible Implementation

interface GraderProtocolConstants
    {
    protected static final String EndOfCommand = "endCommand";
    protected static final String EndOfLine = "\r\n";

    protected static final String CommandSeparator = ":";
    protected static final String ListSeparator = ";";
    protected static final String Assignment = "=";
    }

class GraderResponse implements GraderProtocolConstants
    {
    // Code Not shown, similar to GraderCommand 
    }

class GraderCommand implements GraderProtocolConstants
    {

    protected String command;
    protected String subcommand;
    protected Hashtable attributes = new Hashtable();

    public GraderCommand( String aCommand, String aSubCommand)
        {
        command = aCommand;
        subcommand = aSubCommand;
        }

    public String command()
        {
        return command;
        }

    public String subcommand()
        {
        return subcommand;
        }

    public setAttribute( String attributeName, String attributeValue)
        {
        attributes.put( attributeName, attributeValue);
        }

    public setAttribute( String attributeName, Vector attributeValues)
        {
        attributes.put( attributeName, attributeValues);
        }

    public setAttribute( String attributeName, 
                            Vector namesForPair, Vector valuesForPair)
        {
        Enumeration names = namesForPair.elements();
        Enumeration values = valuesForPair.elements();
        Hashtable nameValuePairs = new Hashtable(); 

        for ( ; names.hasMoreElements() ; ) 
            {
            nameValuePairs.put( names.nextElement(), 
                                    values.nextElement() );
            }

        attributes.put( attributeName, nameValuePairs );
        }

    public setAttribute( String attributeName, 
                            Hashtable nameValuePairs)
        {
        attributes.put( attributeName, nameValuePairs );
        }
    public String toString()
        // translate internal representation of command to format
        // specified in protocol description
        {
        String message = new String();
        message = messge + command + CommandSeparator +
                    subcommand + EndOfLine;

        Enumeration attributeNames = attributes.keys();
        for ( ; attributeNames.hasMoreElements() ; ) 
            {
            message = message + attributeToString( 
                        (String) attributeNames.nextElement() ) +
                        EndOfLine;
            }

        message = message + EndOfCommand + EndOfLine;

        return message;
        }

    private String attributeToString( String name )
        {
        Object value = attributes.get( name );

        if ( value instanceof String ) 
            return processSimpleAttribute( name )
        if ( value instanceof Vector ) 
            return processListAttribute( name )
        if ( value instanceof Hashtable ) 
            return processNameValueAttribute( name )

        }

    private String processSimpleAttribute( String name )
        {
        String attributeString  = new String();
        attributeString  +=  name + CommandSeparator +
                            (String) attributes.get( name );
        return attributeString;
        }

    private String processListAttribute( String name )
        {
        // Have fun with this
        }

    private String processNameValueAttribute( String name )
        {
        // Have fun with this
        }

    public static GraderCommand fromString( String message )
        // translate command as specified in protocol description 
        // to GraderCommand object 

        // Use StringTokenizer to parse string and create
        // GraderCommand object

    }

First Pass at Use In Client


Client Command
login:student
name:first=Roger;last=Smith;id=555-55-5555
password:HiMom
endCommand

Vector studentLabel = new Vector(3);
studentLabel.addElement("first");
studentLabel.addElement("last");
studentLabel.addElement("id");

Vector studentInfo = new Vector(3);
studentLabel.addElement("Roger");
studentLabel.addElement("Smith");
studentLabel.addElement("555-55-5555");

GraderCommand login = new GraderCommand( "login", "student");
login.setAttribute( "password", "HiMom") 
login.setAttribute( "name", studentLabel, studentInfo )

String message = login.asString();

//Now send message to server

Possible Improvement-Subclass of GraderCommand
class StudentLogin extend GraderCommand 
    {
    public StudentLogin( String first, String last, String id) {
        // code missing
        }
        
    public setPassword( String secret) {
        // code missing
        }

    // stuff not show
    }


Client Code

StudentLogin login = new StudentLogin("Roger", "Smith", 
                                "555-55-5555");

login.setPassword( "HiMom") 

String message = login.asString();

//Now send message to server

Possible Improvement - Grader Streams
class GraderOutputStream extends OutputStream
    {
    PrintStream cout;

    public GraderOutputStream( OutputStream out )
        {
        cout = new PrintStream( out );
        }

    public void print( GraderCommand acommand)
        {
        String message = acommand.asString();
        cout.print( message );
        cout.flush();
        }
    }

Client Code

let SimpleOut be an output stream from a socket connected to the server
GraderOutputStream cout = new GraderOutputStream( SimpleOut );
...

StudentLogin login = new StudentLogin("Roger", "Smith", 
                                "555-55-5555");

login.setPassword( "HiMom") 
cout.print( login );

Server Code

let SimpleIn be an input stream from a socket connected to the client
GraderInputStream cin = new GraderInputStream ( SimpleIn );
...

GraderCommand message  = cin.readCommand();

Why divide network communication into layers?
----------