Commit d689bed9 authored by Teemu's avatar Teemu
Browse files

Koottu ohjelma

parent 03f21007
package javaapplication1;
import java.net.*;
import java.io.*;
public class JavaApplication1 {
public static void main(String[] args) {
System.out.println("Main begin");
SocketHandler socketHandler = null;
StreamHandler streamHandler = null;
try {
socketHandler = new SocketHandler();
} catch (IOException e) {
System.err.println("Failed to create SocketHandler object.");
e.printStackTrace();
System.exit(1);
}
try {
streamHandler = socketHandler.openStreamHandler();
} catch (IOException e) {
System.err.println("Failed to open StreamHandler.");
e.printStackTrace();
System.exit(1);
}
int t = 0;
try {
t = streamHandler.readInt();
System.err.println("Received t = " + t);
} catch (IOException e) {
System.err.println("Failed to read int through ObjectInputStream.");
e.printStackTrace();
}
//
Runko r = new Runko();
r.Runko(t , streamHandler.ois , streamHandler.oos, socketHandler.socket);
new Thread(r).start();
//
if (t < 2 || t > 10) {
System.err.println("Illegal value t, sending response...");
try {
streamHandler.writeInt(-1);
} catch (IOException e) {
System.out.println("Failed to send response for illegal value.");
e.printStackTrace();
System.exit(2);
}
System.err.println("Response sent, terminating...");
System.exit(2);
}
System.out.println("Main end");
}
}
class Summain implements Runnable{ // Summaimen prototyyppi, pääasiassa olemassa testimielessä
private int instance;
private int[] sum;
private int[] amo;
private ServerSocket in; // Korvataan objectoutputstreamilla ja objectinputstreamilla tai vastaavalla oliolla
void Summain(int num,int[]summa,int[]maara,ServerSocket input) {
instance = num;
sum=summa;
amo=maara;
in = input; // Edelleen korvataan
}
public void run(){
Socket soketti = null;
ObjectOutputStream outee = null;
ObjectInputStream inee = null;
try {
soketti = in.accept();
outee = new ObjectOutputStream(soketti.getOutputStream());
inee = new ObjectInputStream(soketti.getInputStream());
} catch(IOException e){}
int read = 0;
do {
try{
read = inee.readInt();
} catch (IOException e) {}
if(read != 0) {
sum[instance] += read;
amo[instance]++;
}
} while(read != 0);
try{
soketti.close();
inee.close();
outee.close();
}catch (IOException e) {}
}
}
class Runko implements Runnable{
private int t;
private ObjectInputStream input;
private ObjectOutputStream output;
private Socket omasoketti;
public void Runko(int t_,ObjectInputStream input_, ObjectOutputStream output_, Socket omasoketti_) {
t = t_;
input = input_;
output = output_;
omasoketti = omasoketti_;
}
@Override
public void run() {
// Create appropriate amounts of sums and amount variables
int [] sums = new int[t];
int [] amounts = new int[t];
for(int i =0;i<t;i++) { //Set all above to zero
sums[i] = 0;
amounts[i] = 0;
}
Summain[] summain = new Summain[t]; // Luodaan t kappaletta Summainten viittauksia
ServerSocket[] soketti = new ServerSocket[t];
for(int i = 0;i<t;i++) { //
summain[i] = new Summain(); // Määritetään jokaiselle Summainviittaukselle Summain
try { //
soketti[i] = new ServerSocket(0); // Luodaan uusi ServerSocket seuraavaan vapaaseen porttiin
summain[i].Summain(i,sums,amounts,soketti[i]); // Alustetaan edellämainittu Summain
}catch (IOException e) { // Otetaan kiinni IOException ServerSocketin luomisesta.
} //
new Thread(summain[i]).start(); // Käynnistetään Summain
}
for(int i = 0;i<t;i++) {
try{
output.writeInt(soketti[i].getLocalPort()); // Ilmoitetaan jokaisen Summaimen paikallinen portti Y:lle
output.flush();
} catch (IOException e) {
}
}
int previous = 0; // Käytetään integeriä previous Y:n lähettämän kysymyksen säilömiseen
do { //
try{ //
omasoketti.setSoTimeout(60*1000);
previous = input.readInt(); // Luetaan previoukselle arvo inputista
Answer a = new Answer(); // Luodaan uusi vastaajaluokka
a.Answer(previous, t, sums, amounts, output); // Määritellään a:lle tarvitut arvot
new Thread(a).start(); // Käynnistetään a
}catch (IOException e) {
System.err.println("Seems like Y is no longer transmitting. Ending");
previous = 0;
} //
} while (previous != 0); // Tutkitaan oliko Y:n lähettämä viesti 0
for(int i = 0;i<t;i++) {
try{
soketti[i].close(); // Suljetaan kaikki avoimet Summainsocketit
} catch (IOException e) {
}
}
try{
input.close();
output.close();
omasoketti.close();
} catch (IOException e){
}
}
}
class Answer implements Runnable {
int request;
int t;
int[] sums;
int[] amounts;
ObjectOutputStream out;
public void Answer(int request_, int t_, int[] sums_, int[] amounts_, ObjectOutputStream out_) {
request = request_;
t = t_;
sums = sums_;
amounts = amounts_;
out = out_;
}
@Override
public void run() {
// Vastataan asianomaisesti Y:n tiedusteluun
if(request == 1) { // Tutkitaan palvelimen pyyntö. Jos 1:
int fsum = 0; // Määritellään final sum, eli lopullinen summa johon halutaan sums[]-taulukon alkioiden summa
for (int i = 0;i<t;i++) { //
fsum += sums[i]; // Lisätään jokaisen summainpalvelimen sums[]-alkio fsumiin niin lopputulos on kaikkien summa
} //
try { //
out.writeInt(fsum); // Lähetetään tulos Y:lle
out.flush(); // Puhdistetaan kirjoitusvirta.
} catch (IOException e) { // Ei käsitellä mahdollista virhettä
} //
} else if(request == 2) { // Jos pyyntö 2:
int fsummain = 0; // Oletetaan summaimen 0 sums[]-alkio suurimmaksi
for(int i=1;i<t;i++) { // tutkitaan jokaisen muun summaimen sums[]-alkio
if(sums[i] > sums[fsummain])// Jos havaitaan suurempi sums[]-alkio
fsummain=i; // Tallennetaan fsummain-muuttujaan kyseisen alkion numerotunnus
} //
try { //
out.writeInt(fsummain); // Lähetetään tulos Y:lle
out.flush(); // Puhdistetaan kirjoitusvirta.
} catch (IOException e) { // Ei käsitellä mahdollista virhettä
} //
} else if(request == 3) { // Jos pyyntö 3:
int famount = 0; // Määritellään final amount kuten pyynnöllä 1 final sum
for(int i = 0;i<t;i++) { //
famount += amounts[i]; // Lisätään vastaavasti famountin arvoa jokaisen summaimen saamien lukujen määrällä
} //
try { //
out.writeInt(famount); // Lähetetään tulos Y:lle
out.flush(); // Puhdistetaan kirjoitusvirta.
} catch (IOException e) { // Ei käsitellä mahdollista virhettä
} //
} else {
if(request != 0) { // Jos pyyntö ei ollut 1,2,3 tai 0 (pääohjelma hoitaa 0:n tapauksen)
try{ //
out.writeInt(-1); // Lähetetään Y:lle virhekoodi -1
out.flush(); // Puhdistetaan kirjoitusvirta
} catch (IOException e) { // Ei käsitellä mahdollista virhettä
} //
}
}
}
}
class SocketHandler {
private static final int REMOTEPORT = 3126;
private static final int LOCALPORT = 6666;
private static final int TIMEOUTMILLIS = 5000;
private static final int MAXRETRIES = 5;
private static final InetAddress REMOTEHOST = bytesToAddress(new byte[] {127, 0, 0, 1});
/**
* Turns an array of bytes into an InetAddress.
*
* @param bytes The array to be converted.
* @return The InetAddress which is the result of this conversion, or null if the conversion
* fails.
*/
private static InetAddress bytesToAddress(byte[] bytes) {
try {
return InetAddress.getByAddress(bytes);
} catch (UnknownHostException ex) {
System.err.println("Failed in creating InetAddress");
ex.printStackTrace();
System.exit(3);
}
return null;
} // bytesToAddress(byte[])
private ServerSocket serverSocket;
public Socket socket;
/**
* Creates a new SocketHandler.
*
* @throws IOException If creating the SocketHandler fails.
*/
public SocketHandler() throws IOException {
this.serverSocket = new ServerSocket(LOCALPORT);
this.serverSocket.setSoTimeout(TIMEOUTMILLIS);
} // SocketHandler()
/**
* Closes the resources handled by this SocketHandler.
*
* @throws IOException If closing either the Socket or the ServerSocket fails.
*/
public void close() throws IOException {
if (!this.socket.isClosed()) {
this.socket.close();
}
if (!this.serverSocket.isClosed()) {
this.serverSocket.close();
}
} // close()
/**
* Uses this SocketHandler to create a StreamHandler object that contains the streams from this
* SocketHandler's socket.
*
* @throws IOException if opening one of the sockets fails.
*/
public StreamHandler openStreamHandler() throws IOException {
int timesRetried = 0;
do {
this.sendPortNumber(REMOTEHOST, REMOTEPORT, LOCALPORT);
try {
this.socket = this.serverSocket.accept();
try {
this.socket.setSoTimeout(TIMEOUTMILLIS);
} catch (SocketException e) {
System.err.println("Failed in setting timeout for socket.");
e.printStackTrace();
}
return new StreamHandler(new ObjectInputStream(this.socket.getInputStream()),
new ObjectOutputStream(this.socket.getOutputStream()));
} catch (SocketTimeoutException ex) {
System.err.println("Socket timed out, trying again...");
timesRetried++;
}
} while (timesRetried < MAXRETRIES);
if (timesRetried == MAXRETRIES) {
System.err.println("Failed to receive connection");
System.exit(1);
}
return null;
} // openStreamHandler()
/**
* Sends the port number localPort to the port remotePort at remoteHost
*
* @param remoteHost The machine to which the port number needs to be sent
* @param remotePort The port on remoteHost to send to
* @param localPort The local port number to be sent to remoteHost
* @throws IOException If the transmission fails
*/
private void sendPortNumber(InetAddress remoteHost, int remotePort, int localPort) {
try (DatagramSocket dsocket = new DatagramSocket(0)) {
String portNumber = Integer.toString(localPort);
byte[] portHolder = portNumber.getBytes();
DatagramPacket request =
new DatagramPacket(portHolder, portHolder.length, remoteHost, remotePort);
dsocket.send(request);
} catch (SocketException e) {
System.err.println("Failed in opening DatagramSocket.");
e.printStackTrace();
} catch (IOException e) {
System.err.println("Failed in sending request packet through UDP");
e.printStackTrace();
}
} // sendPort(InetAddress, int, int)
}
class StreamHandler {
public ObjectInputStream ois;
public ObjectOutputStream oos;
/**
* Packs the parameters ois and oos into a StreamHandler object.
*
* @param ois The ObjectInputStream to be placed in this object.
* @param oos The ObjectOutputStream to be placed in this object.
*/
public StreamHandler(ObjectInputStream ois, ObjectOutputStream oos) {
this.ois = ois;
this.oos = oos;
} // StreamHandler(ObjectInputStream, ObjectOutputStream)
/**
* Closes the streams handled by this object.
*
* @throws IOException If closing one of the streams fails.
*/
void close() throws IOException {
this.ois.close();
this.oos.close();
} // close()
/**
* Reads an int from the input stream contained in this object.
*
* @return The int read from the stream.
* @throws IOException If reading from the stream fails.
*/
int readInt() throws IOException {
return this.ois.readInt();
} // readInt()
/**
* Write an int to the output stream contained in this object.
*
* @param n The int to be written out.
* @throws IOException If writing to the stream fails.
*/
void writeInt(int n) throws IOException {
this.oos.writeInt(n);
this.oos.flush();
} // writeInt(int)
} // class StreamHandler
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment