A Simple Dictionary clientTo learn how to make, in Java, a TCP/IP connection and how to exchange data over the connection.To study and understand the implementation of an application level proto
A Simple Dictionary clientTo learn how to make, in Java, a TCP/IP connection and how to exchange data over the connection.To study and understand the implementation of an application level proto
All assignments in this course must compile and run on the Linux undergrad servers provided for student use. If your program does not compile and at least start to execute it WILL NOT BE MARKED and a grade of 0 will be awarded.Consequently, if you use a different environment be sure to check that your solution works on the ugrad machines as you will be graded on how it works on the department machines not on your own machine. All instructions for accessing code, building programs, using source code control tools etc, assume you are working on these machines. If you are working in a different environment commands and parameters may be different. Given the diverse collection of machines it is not possible for us to provide instruction and guidance on how to use these tools or their analogues across these varied environments. Pleas for leniency or special consideration of the nature "But it works on my laptop under ...." will not be entertained, so make sure it works on the undergraduate Linux servers and allow time for testing in that environment so that you are confident your code works as expected there.
In addition all marking will be done on the master branch so make sure all of your changes are properly merged into the master branch. Requests to mark other branches will not be entertained.
In this assignment you will use the Java socket related classes to create a client program to retrieve definitions from a dictionary server using the application level protocol described in RFC 2229. The strategies you need to employ are similar to those used by the many client applications you use on a daily basis. Your program will read input from the command line, and based on those commands communicate with a dictionary server to ultimately retrieve word definitions. You will only be implementing a subset of the commands that can be sent to a dictionary server. Note to facilitate automated testing the output of your program must be exactly as specified. Don't go adding extra information etc.
Your program will provide a simple shell-style interface to the user. This interface will read application commands provided by the user, and interpret them according to the description of each command given below. Whenever the program is expecting input it is to print the text 'csdict> ' (Note the blank character after the >). It is to leave the cursor at that position awaiting input. (i.e. the program is not to print 'csdict>' on a line by itself.) You may assume that command lines do not have more than 255 characters. Empty lines and lines starting with the character '#' are to be silently ignored, and a new prompt displayed.
The following table describes the application commands to implement:
Application Command | Description |
---|---|
open SERVER PORT | Opens a new control connection to a dictionary server, as specified by the command's parameters. The server name can be either a domain name or an IP address in dotted form. The PORT parameter is optional, if missing the default dictionary server port (2628) is used. This command is considered an unexpected command if it is given when a control connection is already open. |
dict | Retrieve and print the list of all the dictionaries the server supports. Each line will consist of a single word that is the the name of a dictionary followed by some information about the dictionary. You simply have to print each of these lines as returned by the server. |
set DICTIONARY | Set the dictionary to retrieve definitions or matches from. The string representing the dictionary name can be anything. However for subsequent define and match commands to work the string will have to be eiher the first word on one of the lines returned by the dict command or one of the required virtual databases defined in section 3.4 of the RFC. The default dictionary to use if the set command has not been given is "*". When a connection is established to a dictionary server, the dictionary to use is initially set to "*". Multiple set commands simply result in a new dictionary to search being set. Multiple set commands do not result in the building of a collection of dictionaries to search. Note your program is not to check/ verify if the string provided as a dictionary name is, in fact, valid. If the name is invalid, define and match commands will return an error and the program will report the problem at that time. |
currdict | Prints the name of the current dictionary being used. Initially this value is "*". |
define WORD | Retrieve and print all the definitions for WORD. WORD is looked up in the dictionary or dictionaries as specified through the set command. For each definition returned print on a single line, and left justified, the name of the dictionary. On the next line start printing the returned definition. If the word can't be found, and no definitions are returned, you are to print **No definition found** on a single line by itself and then issue a match command using the server's default matching strategy against all of the dictionaries on this server and then print all of its responses. If there are no matches then the program is print, on a line by itself, ***No dictionaries have a definition for this word*** If this command returns a status indicating that the dictionary does not exist then error message 930 (see below) is printed. Note this command will not result in a change to the which dictionary(ies) will be used in subsequent commands. |
match WORD | Retrieve and print all the exact matches for WORD. WORD is looked up in the dictionary or dictionaries as specified through the set command. The responses from the server will consist of one or more lines of form database word If no matches are found print ****No matching word(s) found**** on a single line by itself. This command is most useful when you want to determine which dictionary a word occurs in before selecting a dictionary to retrieve the definition from. If this command returns a status indicating that that dictionary does not exist then error message 930 (see below) is printed. |
prefixmatch WORD | Retrieve and print all the prefix matches. for WORD. WORD is looked up in the dictionary or dictionaries as specified through the set command. The responses from the server will consist of one or more lines of form database word If the word can't be found simply print *****No prefix matches found***** on a single line by itself. If this command returns a status indicating that that dictionary does not exist then error message 930 (see below) is printed. |
close | After sending the appropriate command to the server and receiving a response, closes the established connection and enters a state where the next command expected is open or quit. |
quit | Closes any established connection and exits the program. This command is valid at any time. |
A command line is composed of a command, as described above, followed by zero or more parameters. The case of the command is to to be ignored. As result the commands match, MATCH, and mAtCh are all the same command. The command is separated from any parameters by one or more spaces and/or tabs. The case of the parameters is significant. Tabs or spaces at the end of the line are to be ignored. Your dictionary client may detect certain types of errors. When an error is detected the client is to print, on a new line, a single line consisting of a 3 digit number starting with 9 and a short text message from the list of error messages provided below. In the list below, the message to print is in bold and it is followed by a description of the error it corresponds to. If needed, the description will also describe how processing is to proceed. Note that the client is only to exit when it gets the quit command a ctl-c or ctl-d. The client doesn't need need to detect ctl-c as it is handled by the system and ctl-d will result in an end-of-file indication being returned during a read. The application is to handle the end-of-file and silently exit.
Whenever you send a command to the server it will respond in some fashion. A detailed description of how a server will response can be found in section 2.4 of the RFC but basically responses consist of collections of Status and Text responses. With respect to output for things like lists of dictionaries matches, etc you simply have to print the Text Responses. However prior to the printing of each definition you are to print a line starting with @ followed by a blank and then the name of the dictionary as returned by the server. Such a line might look like:
@ easton "Easton's 1897 Bible Dictionary"
Only print the the Status responses if the -d command line option is provided (see below). For text responses, always print the line the contains nothing but a period on it.
Your program will be run at the command line by doing
java -jar CSdict.jar [-d].
(The supplied Makefile will also run the command if you enter make run)
Your program is to always print the text responses and if the if the -d option is present that output is augmented with all commands sent by the client to the dictionary server must be echoed to standard output with the prefix '--> ' (Note the space after the -->). In addition status response messages received from by the client program must be printed with the prefix '<-- ' (Note the space after the <--). The status responses are to be printed as soon as they are received and before the output that would be printed if "-d" hadn't be given. Except for the text described above, no other text is to be printed by your program unless it listed as an error message your program is supposed to print.
If the -d option is not supplied then you are to print only the results and none of the status information.
Remember, You are only required to implement a subset of the protocol so some of the material in the references goes beyond what you need. Keep in mind that the RFC describes the data (protocol) exchanges between the client (i.e. what you are writing) and a dictionary server. It does not describe the commands accepted by your client program, those are described in the table above.
Don't spend too much time in the implementation of the shell. A simple show prompt, read line, identify command, run command is sufficient.
Don't try to implement this assignment all at once. Instead incrementally build and simultaneously test the solution. A suggested strategy is to:
For testing purposes you can connect to any dictionary server, like test.dict.org on port 2628. Your program is expected to work with a wide variety of dictionary servers so you should locate other servers and try your program against them. Constantly typing in the commands for your client can become a bit tedious after awhile. To reduce your typing load you might want to checkout the command autoexpect on the cs machines. It basically lets you issue a series of commands, record the output and then play the commands back. You would start by doing:
autoexpect java -jar CSdict.jar
In the folder where CSdict.jar lives. You can then type in the sequence of commands that you wish to test and quit at the end. Once you're done autoexpect will generate a script.exp file that you can run by doing
./script.exp
You may discuss this assignment with your classmates, but you must do your work only with your partner. You are not allowed to show your code, even for discussion or explanatory purposes to other classmates.
Your code is to be developed for the Undergrad Linux server machines (e.g. ). The TAs will test your code on these machines, so test your program extensively in this environment, including your Makefile.
Style and comments are part of the evaluation, so keep your code clear, clean and well-documented. Your code should be easy to read, with blank lines delineating blocks of functionality, and avoiding long lines. Use proper comments and names for variables and methods that accurately reflect their purpose. Use methods to deal with long blocks of code and repeated functionality.
You are to use git to handin all materials for this assignment. The last push of your repo is what will be marked. Any late penalty will be computed based on the time of your last push. Any commits pushed after the 48-hour deadline for late submissions will be ignored.
Make sure your git repository on the department stash server has the version of the following files:
Everyone is required to use a GIT repository on the department's stash server to manage the source code for this assignment and to hand the final version in. Furthermore, you are required to regularly ``push'' your changes to the server. (Marks are awarded for doing this.)
In this course we will be using git and a Stash code repository server to perform the source code management of the assignments. Stash is essentially the commercial version of bitbucket and is hosted by the department. The URI to the stash server is:Make sure to specify the HTTPS part of the URI. The account name and password are the same as your undergraduate department ID. When working in pairs, a git repository needs to be setup such that both partners will have access to it. Before you can access the git repo with your copy of the assignment, you will need to register your team using the A1 Registration Link that is available through Connect in the Assignment content section. You must do this even to get access to the starting code. Both team members must register before the repo for the team will be created. If you work alone, which you are strongly encouraged not to do, you need to leave the partner name blank. Upon creation, the URI of the repo will be displayed at the bottom of the form; it will be something like
https://stash.ugrad.cs.ubc.ca:8443/git/CPSC317_2015w2_201/cs317_a1_r2d2_c3p0.git
To get your assignment you will need to have access to a version of git. Fortunately, the department Linux machines all have a command line version of git installed. Before creating your copy of the repo you need to know its URI which was displayed when all partners completed registration. You can also determine the repo name by logging into Stash.
When you login to the Stash server, you are presented with a list of projects you have access to. With respect to this course, you should see a project called CS317_2015W2_201 and its associated key CS317_2015W2_201. If you click on that project you will be taken to a list of repositories. A repository is essentially a collection of code objects that form some sort of cohesive unit. In this case it is assignment 1. The repository name will be cs317_a1_ followed by the undergrad ID of you and your partner. You have permission to copy from and write to this repository. You are expected to keep the repository in sync with your code so that you can track the changes you make and to simplify recovery if you accidentally delete files or code. In addition this helps simplify the process of keeping copies of the code you are working on in sync across the various machines you and your partner might be using. (e.g. a department machine, your laptop, a home PC etc.) You can also use the tools within Stash to compare different versions of files to see what changes have been made. Once in your repo, click on ... towards the top left. One of the menu items will be clone. Click on clone, and then select HTTP from the pull-down menu if it shows ssh. Copy the URI shown in the box so that it can be pasted to the appropriate git command. The URI will look something like:
https://stash.ugrad.cs.ubc.ca:8443/git/CPSC317_2015w2_201/cs317_a1_r2d2_c3p0.git
To retrieve the assignment code on any machine you will be developing your code on you will need to have a version of git installed. The department has installed a command line version of git on the undergrad Linux machines. git is a complicated and powerful system, but we will try to keep things simple. If you need help installing git on your own machine, or want to learn more, a good starting point is the book you can access at . The following instructions should help you get going and assume you are using a department Linux machine and any URIs correspond to the ones provided when you registered your partner or as determined via Stash.
As you work on your code you will want to periodically "push" changes to the Stash repository. It is highly recommended that you do this frequently. You might want to push these changes every time you stop working on the code and when you get to important implementation milestones. To start developing an understanding of how to use git, read chapter 2 of the above reference. Some commands that might be useful are:
Given how git works each partner can work on the assignment separately and then use combinations of git add, commit and push commands to commit the changes and push them to the repository. To get changes a partner has pushed use git pull; or git fetch combined with git merge . Keep in mind that you can always refer back to the git documentation.
NOTE: You are expected to regularly check-in the work you have done throughout the assignment. To encourage this part of the grade for this assignment will be based on a regular and reasonable check-ins of your code. It is expected that both partners will contribute to the assignment and check-in code. It is accepted that the checking in of code may not be 50/50, but if only one person is checking in code then questions might be raised about who is doing the work and marks adjusted accordingly.