001    //package edu.unima.ky.parallel;
002    
003    import java.io.IOException;
004    import java.net.Socket;
005    import java.io.ObjectInputStream;
006    import java.io.ObjectOutputStream;
007    
008    /**
009     * SocketChannel.
010     * This class creates a communication channel using a socket.
011     * @author Akitoshi Yoshida.
012     * @author Heinz Kredel.
013     */
014    
015    public class SocketChannel implements ObjectChannel {
016      /**
017       * input stream from the socket.
018       */
019      private ObjectInputStream in;
020    
021      /**
022       * output stream to the socket.
023       */
024      private ObjectOutputStream out;
025    
026      /**
027       * socket.
028       */
029      private Socket soc;
030    
031      /**
032       * Constructs a socket channel on the given socket s.
033       * @param s socket.
034       */
035      public SocketChannel(Socket s) throws IOException {
036        soc = s;
037        if (checkOrder(s)) {
038          in = new ObjectInputStream(s.getInputStream());
039          out = new ObjectOutputStream(s.getOutputStream());
040        }
041        else {
042          out = new ObjectOutputStream(s.getOutputStream());
043          in = new ObjectInputStream(s.getInputStream());
044        }
045      }
046    
047      /**
048       * Sends an object.
049       */
050      public void send(Object v) throws IOException {
051        synchronized (out) {
052          out.writeObject(v);
053        }
054      }
055    
056      /**
057       * Receives an object.
058       */
059      public Object receive() throws IOException, ClassNotFoundException {
060        Object v = null;
061        synchronized (in) {
062          v = in.readObject();
063        }
064        return v;
065      }
066    
067      /**
068       * Closes the channel.
069       */
070      public void close() {
071        if (in != null) {
072          try { in.close(); } catch (IOException e) { }
073        }
074        if (out != null) {
075          try { out.close(); } catch (IOException e) { }
076        }
077        if (soc != null) {
078          try { soc.close(); } catch (IOException e) { }
079        }
080      }
081    
082      /*
083       * Determines the order of stream initialization.
084       * @param s A socket's object.  
085       */
086      private boolean checkOrder(Socket s) throws IOException {
087        // first use the port numbers as the key
088        int p1 = s.getLocalPort();
089        int p2 = s.getPort();
090        if (p1 < p2) return true;
091        else if (p1 > p2) return false;
092    
093        // second use the inetaddr as the key
094        int a1 = s.getLocalAddress().hashCode();
095        int a2 = s.getInetAddress().hashCode();
096        if (a1 < a2) return true;
097        else if (a1 > a2) return false;
098    
099        // this shouldn't happen
100        throw new IOException();
101      }
102    }