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
- Issues
- States
- General Comments
- Client Command Structure
- Server Response Structure
- Making Connection
- Guest State
- Login SubCommands
- Get SubCommands
- Student State
- InstructorState
- Possible Implementation
- First Pass at Use In Client
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
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
- 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
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
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
Commands
login:student
login:instructor
get:listOfDepartments
get:departmentCourses
get:courseSummary
quit:now
Guest State
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
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
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
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
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
}
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?