-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 47a7b1e
Showing
7 changed files
with
447 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<classpath> | ||
<classpathentry kind="src" path="src"/> | ||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> | ||
<classpathentry kind="output" path="bin"/> | ||
</classpath> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.DS_Store | ||
/bin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<projectDescription> | ||
<name>ex22-square</name> | ||
<comment></comment> | ||
<projects> | ||
</projects> | ||
<buildSpec> | ||
<buildCommand> | ||
<name>org.eclipse.jdt.core.javabuilder</name> | ||
<arguments> | ||
</arguments> | ||
</buildCommand> | ||
</buildSpec> | ||
<natures> | ||
<nature>org.eclipse.jdt.core.javanature</nature> | ||
</natures> | ||
</projectDescription> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package square; | ||
|
||
import java.io.*; | ||
import java.net.Socket; | ||
|
||
/** | ||
* SquareClient is a client that sends requests to the SquareServer | ||
* and interprets its replies. | ||
* A new SquareClient is "open" until the close() method is called, | ||
* at which point it is "closed" and may not be used further. | ||
*/ | ||
public class SquareClient { | ||
private Socket socket; | ||
private BufferedReader in; | ||
private PrintWriter out; | ||
// Rep invariant: socket, in, out != null | ||
|
||
/** | ||
* Make a SquareClient and connect it to a server running on | ||
* hostname at the specified port. | ||
* @throws IOException if can't connect | ||
*/ | ||
public SquareClient(String hostname, int port) throws IOException { | ||
socket = new Socket(hostname, port); | ||
in = new BufferedReader(new InputStreamReader(socket.getInputStream())); | ||
out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); | ||
} | ||
|
||
/** | ||
* Send a request to the server. Requires this is "open". | ||
* @param x number to square | ||
* @throws IOException if network or server failure | ||
*/ | ||
public void sendRequest(int x) throws IOException { | ||
out.print(x + "\n"); | ||
out.flush(); // important! make sure x actually gets sent | ||
} | ||
|
||
/** | ||
* Get a reply from the next request that was submitted. | ||
* Requires this is "open". | ||
* @return square of requested number | ||
* @throws IOException if network or server failure | ||
*/ | ||
public int getReply() throws IOException { | ||
String reply = in.readLine(); | ||
if (reply == null) { | ||
throw new IOException("connection terminated unexpectedly"); | ||
} | ||
|
||
try { | ||
return Integer.valueOf(reply); | ||
} catch (NumberFormatException nfe) { | ||
throw new IOException("misformatted reply: " + reply); | ||
} | ||
} | ||
|
||
/** | ||
* Closes the client's connection to the server. | ||
* This client is now "closed". Requires this is "open". | ||
* @throws IOException if close fails | ||
*/ | ||
public void close() throws IOException { | ||
in.close(); | ||
out.close(); | ||
socket.close(); | ||
} | ||
|
||
|
||
|
||
|
||
private static final int N = 100; | ||
|
||
/** | ||
* Use a SquareServer to square all the integers from 1 to N. | ||
*/ | ||
public static void main(String[] args) { | ||
try { | ||
SquareClient client = new SquareClient("localhost", SquareServer.SQUARE_PORT); | ||
|
||
// send the requests to square 1...N | ||
for (int x = 1; x <= N; ++x) { | ||
client.sendRequest(x); | ||
System.out.println(x + "^2 = ?"); | ||
} | ||
|
||
// collect the replies | ||
for (int x = 1; x <= N; ++x) { | ||
int y = client.getReply(); | ||
System.out.println(x + "^2 = " + y); | ||
} | ||
|
||
client.close(); | ||
} catch (IOException ioe) { | ||
ioe.printStackTrace(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package square; | ||
|
||
import java.util.concurrent.BlockingQueue; | ||
import java.util.concurrent.LinkedBlockingQueue; | ||
|
||
/** | ||
* Squares integers. | ||
*/ | ||
class Squarer { | ||
|
||
private final BlockingQueue<Integer> in; | ||
private final BlockingQueue<SquareResult> out; | ||
// Rep invariant: in, out != null | ||
|
||
/** | ||
* Make a squarer that will listen for requests and generate replies. | ||
* @param requests queue to receive requests from | ||
* @param replies queue to send replies to | ||
*/ | ||
public Squarer(BlockingQueue<Integer> requests, BlockingQueue<SquareResult> replies) { | ||
this.in = requests; | ||
this.out = replies; | ||
} | ||
|
||
/** | ||
* Start handling squaring requests. | ||
*/ | ||
public void start() { | ||
new Thread(new Runnable() { | ||
public void run() { | ||
while (true) { | ||
// TODO: we may want a way to stop the thread | ||
try { | ||
// block until a request arrives | ||
int x = in.take(); | ||
// compute the answer and send it back | ||
int y = x * x; | ||
out.put(new SquareResult(x, y)); | ||
} catch (InterruptedException ie) { | ||
ie.printStackTrace(); | ||
} | ||
} | ||
} | ||
}).start(); | ||
} | ||
} | ||
|
||
/** | ||
* An immutable squaring result message. | ||
*/ | ||
class SquareResult { | ||
private final int input; | ||
private final int output; | ||
|
||
/** | ||
* Make a new result message. | ||
* @param input input number | ||
* @param output square of input | ||
*/ | ||
public SquareResult(int input, int output) { | ||
this.input = input; | ||
this.output = output; | ||
} | ||
|
||
// TODO: we will want more observers, but for now... | ||
|
||
@Override public String toString() { | ||
return input + "^2 = " + output; | ||
} | ||
} | ||
|
||
public class SquareQueue { | ||
|
||
/** | ||
* Create and use a squarer. | ||
*/ | ||
public static void main(String[] args) { | ||
|
||
BlockingQueue<Integer> requests = new LinkedBlockingQueue<>(); | ||
BlockingQueue<SquareResult> replies = new LinkedBlockingQueue<>(); | ||
|
||
Squarer squarer = new Squarer(requests, replies); | ||
squarer.start(); | ||
|
||
try { | ||
// make a request | ||
requests.put(42); | ||
|
||
// maybe do something concurrently... | ||
|
||
// read the reply | ||
System.out.println(replies.take()); | ||
} catch (InterruptedException ie) { | ||
ie.printStackTrace(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package square; | ||
import java.io.*; | ||
import java.net.ServerSocket; | ||
import java.net.Socket; | ||
|
||
/** | ||
* SquareServer is a server that squares integers passed to it. | ||
* It accepts requests of the form: | ||
* Request ::= Number "\n" | ||
* Number ::= [0-9]+ | ||
* and for each request, returns a reply of the form: | ||
* Reply ::= (Number | "err") "\n" | ||
* where a Number is the square of the request number, | ||
* or "err" is used to indicate a misformatted request. | ||
* SquareServer can handle only one client at a time. | ||
*/ | ||
public class SquareServer { | ||
/** Default port number where the server listens for connections. */ | ||
public static final int SQUARE_PORT = 4949; | ||
|
||
private ServerSocket serverSocket; | ||
// Rep invariant: serverSocket != null | ||
|
||
/** | ||
* Make a SquareServer that listens for connections on port. | ||
* @param port port number, requires 0 <= port <= 65535 | ||
*/ | ||
public SquareServer(int port) throws IOException { | ||
serverSocket = new ServerSocket(port); | ||
} | ||
|
||
/** | ||
* Run the server, listening for connections and handling them. | ||
* @throws IOException if the main server socket is broken | ||
*/ | ||
public void serve() throws IOException { | ||
while (true) { | ||
// block until a client connects | ||
Socket socket = serverSocket.accept(); | ||
try { | ||
handle(socket); | ||
} catch (IOException ioe) { | ||
ioe.printStackTrace(); // but don't terminate serve() | ||
} finally { | ||
socket.close(); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Handle one client connection. Returns when client disconnects. | ||
* @param socket socket where client is connected | ||
* @throws IOException if connection encounters an error | ||
*/ | ||
private void handle(Socket socket) throws IOException { | ||
System.err.println("client connected"); | ||
|
||
// get the socket's input stream, and wrap converters around it | ||
// that convert it from a byte stream to a character stream, | ||
// and that buffer it so that we can read a line at a time | ||
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); | ||
|
||
// similarly, wrap character=>bytestream converter around the | ||
// socket output stream, and wrap a PrintWriter around that so | ||
// that we have more convenient ways to write Java primitive | ||
// types to it. | ||
PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); | ||
|
||
try { | ||
// each request is a single line containing a number | ||
for (String line = in.readLine(); line != null; line = in.readLine()) { | ||
System.err.println("request: " + line); | ||
try { | ||
int x = Integer.valueOf(line); | ||
// compute answer and send back to client | ||
int y = x * x; | ||
System.err.println("reply: " + y); | ||
out.print(y + "\n"); | ||
} catch (NumberFormatException e) { | ||
// complain about ill-formatted request | ||
System.err.println("reply: err"); | ||
out.println("err"); | ||
} | ||
// important! flush our buffer so the reply is sent | ||
out.flush(); | ||
} | ||
} finally { | ||
out.close(); | ||
in.close(); | ||
} | ||
} | ||
|
||
/** | ||
* Start a SquareServer running on the default port. | ||
*/ | ||
public static void main(String[] args) { | ||
try { | ||
SquareServer server = new SquareServer(SQUARE_PORT); | ||
server.serve(); | ||
} catch (IOException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
} |
Oops, something went wrong.