




















Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
Material Type: Assignment; Class: CLIENT-SERVER PROGRAMMING; Subject: Computer Science; University: San Diego State University; Term: Fall 2000;
Typology: Assignments
1 / 28
This page cannot be seen from the preview
Don't miss anything!





















Doc 13 Assignment 1 Solution
- Fall Semester, Assignment 1 Solution
Problem areas:
System.arraycopy
Primitive to copy arrays
System.arrayCopy(Source, sourceStartIndex, Destination, destinationStartIndex, lengthToCopy )
ByteQueue
Growable queue of bytes
Used in reading data from server
ByteReader
Reads bytes from an input stream
Not a proper Java Reader
Methods:
readUpTo( byte[] pattern) readThrough( byte[] pattern) read( int length) skip( int length) readAll() isAtEnd()
ByteQueue public void add(byte[] bytes, int offset, int length) { if (queueSize + length > elements.length) growelements();
System.arraycopy(bytes, offset, elements,queueSize, length); queueSize = queueSize + length; }
public byte[] remove( int size) { int avaliableSize = Math.min( size, queueSize); byte[] response = new byte[avaliableSize]; System.arraycopy(elements, 0, response, 0,avaliableSize); System.arraycopy(elements, avaliableSize, elements, 0, queueSize - avaliableSize); queueSize = queueSize - avaliableSize; return response; }
public boolean contains(byte[] pattern) { return -1 != indexOf( pattern);
ByteQueue
public int indexOf( byte[] pattern ) { for (int k = 0; k < queueSize - pattern.length + 1; k++) { int offset =0; while (offset < pattern.length && pattern[offset] == elements[k + offset]) offset++; if (offset == pattern.length) return k; } return -1; }
private void growelements() { byte[] oldelements = elements; elements = new byte[oldelements.length * 2 ]; System.arraycopy(oldelements, 0, elements, 0,queueSize); }
package WebProxy;
import java.io.*;
public class ByteReader { static int READ_SIZE = 512; static int BUFFER_CAPACITY = 1024 * 4; BufferedInputStream in; ByteQueue buffer = new ByteQueue(BUFFER_CAPACITY); boolean atEOF = false;
public ByteReader( InputStream input) { in = new BufferedInputStream( input ); }
public byte[] readUpTo( byte[] pattern) throws IOException { int location = readToFindIndexOf( pattern); return remove( location); }
public byte[] readThrough( byte[] pattern) throws IOException { int location = readToFindIndexOf( pattern); return remove( location + pattern.length);
ByteReader
public byte[] read( int length) throws IOException { while ( (!isAtEnd() && length > buffer.size())) readBlock(); return remove( length); }
public void skip( int length) throws IOException { read( length); }
public byte[] readAll() throws IOException { while (!isAtEnd()) readBlock(); return remove( buffer.size()); }
public boolean isAtEnd() { return atEOF; }
private int readToFindIndexOf( byte[] pattern) throws IOException { int location; while ((location = buffer.indexOf( pattern)) == -1) readBlock(); return location;
public void testByteInput() throws IOException { String response= "caaaat\r\n" + "do\rg\r\n\r\nacat"; ByteReader in = new ByteReader(new StringBufferInputStream( response));
byte[] answer = in.readUpTo("\r\n".getBytes()); assert( "line 1", (new String( answer)).equals( "caaaat")); in.skip( 2); answer = in.readThrough("\r\n".getBytes()); assert( "line 2", (new String( answer)).equals( "do\rg\r\n")); in.readThrough("\r\n".getBytes()); answer = in.readAll(); assert( "line 3", (new String( answer)).equals( "acat")); assert( "end", ( in.isAtEnd())); }
The http request and response have structure, which is similar
Give each a class to parse/create requests and responses
Use super class to leverage common structure
HttpTransaction
public byte[] toBytes() { if (!hasBody()) return toString().getBytes(); String headerString = toString(); int length = headerString.length() + body.length; byte[] transaction = new byte[length]; System.arraycopy(headerString.getBytes(), 0, transaction, 0, headerString.length()); System.arraycopy(body, 0, transaction, headerString.length(), body.length); return transaction; }
public boolean hasContentLength() { return (headers.containsKey( "Content-length" ) || headers.containsKey( "Content-Length" )); }
public int contentLength() { String length = null; if (headers.containsKey( "Content-length" ) ) length = (String)headers.get( "Content-length" ); else length = (String)headers.get( "Content-Length" ); return Integer.parseInt (length);
HttpTransaction
public boolean hasBody() { return hasContentLength(); }
public byte[] body() { return body; }
void parseBody( ByteReader input) throws IOException { if (hasContentLength()) { int bodyLength = contentLength(); body = input.read( bodyLength); } else body = input.readAll(); }
public String toString() { if (hasHeaders()) return firstLineToString() + headerToString(); else return firstLineToString();
HttpTransaction
void parseHeaders( ByteReader input ) { try { String requestLine = readLine(input); while (requestLine.length() > 0 ) { int separatorIndex = requestLine.indexOf(':'); String name = requestLine.substring(0, separatorIndex); String value = requestLine.substring(separatorIndex + 1).trim(); headers.put( name, value); requestLine = readLine(input); } } catch (IOException readError ) { } }
String readLine( ByteReader input ) throws IOException { byte[] line = input.readUpTo( "\r\n".getBytes()); input.skip(2); return new String( line, 0); }
package WebProxy;
import java.io.IOException;
public class HttpResponse extends HttpTransaction { String statusLine;
public String firstLineToString() { return statusLine + "\r\n"; }
void parseFirstLine(ByteReader input) { try { statusLine = readLine(input); } catch (IOException readError ) { } } public boolean hasBody() { return true; }