1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
| package common;
import java.io.*;
import java.net.ConnectException;
import java.net.ServerSocket;
import java.net.Socket;
public class Channel {
// This class implements a channel that can be written to and read
// from by DirectoryServers, PeerServers and PeerClients.
// The socket that is associated with this side of the Channel:
Socket socket = null;
// The streams in/out are used to read/write to/from the channel:
ObjectInputStream in = null;
ObjectOutputStream out = null;
// Whether debugging messages should be displayed:
boolean debuggingMessages = true;
public Channel (ServerSocket serverSocket, boolean displayDebuggingMessages) throws ChannelException {
// Calling this constructor signals that the caller wants to
// wait for connections to the given port, alternatively pick
// up a connection that is already waiting. The constructor
// does not return until a connection is established. If there
// is a problem, a ChannelException is thrown. This is usually
// a fatal error and the program should be terminated.
this.debuggingMessages = displayDebuggingMessages;
try {
if (displayDebuggingMessages) {
System.out.println(" Channel: waiting for somebody to connect ");
}
// Accept a connection, i.e. either pick up a waiting
// connection or wait until somebody connects. Note that
// the accept method blocks until a connection is
// available.
socket = serverSocket.accept();
if (displayDebuggingMessages) {
System.out.println(" Channel: connection established");
}
// Set up the in/out streams for reading and writing:
setupStreams();
}
catch (Exception e) {
System.out.println("Channel: an error occurred while waiting for somebody to connect ");
e.printStackTrace();
ChannelException ce = new ChannelException(e);
throw(ce);
}
}
public Channel (String address, int portNumber, boolean displayDebuggingMessages)
throws ConnectException, ChannelException {
// Calling this constructor signals that the caller wants to
// connect to the given address and port. It will wait until
// the other side replies. If the connection is refused, a
// java.net.ConnectException is thrown. This is usually not a
// fatal error, so the program can continue if the exception
// is caught by the calling method. If the connection cannot
// be established for some other reason, a ChannelException is
// thrown. This is usually a fatal error and the program
// should be terminated.
this.debuggingMessages = displayDebuggingMessages;
try {
if (displayDebuggingMessages) {
System.out.println(" Channel: establishing a connection to " +
address + ", port " + portNumber);
}
// Create a connection, i.e. a socket, to the given
// address and wait until there is a reply:
socket = new Socket(address, portNumber);
if (displayDebuggingMessages) {
System.out.println(" Channel: connection established");
}
// Set up the in/out streams for reading and writing:
setupStreams();
}
catch (ConnectException e) {
// The connection was refused. This is not necessarily a
// fatal error so we throw the exception to the caller of
// this method that can catch it and take some suitable
// action.
if (displayDebuggingMessages) {
System.out.println(" Channel: connection refused");
}
throw e;
}
catch (Exception e) {
// Some other problem occurred while setting up the
// connection. This is considered a fatal error and the
// program is terminated.
System.out.println("Channel: an error occurred while trying to connect to " +
address + ", port " + portNumber);
e.printStackTrace();
ChannelException ce = new ChannelException(e);
throw(ce);
}
}
private void setupStreams () throws ChannelException {
// This method is called when a socket has been established.
// It sets up the in/out streams for the channel. If there is
// a problem, a ChannelException is thrown. This is usually a
// fatal error and the program should be terminated.
try {
// Get the general in/out streams that are already
// associated with the socket:
InputStream generalIn = socket.getInputStream();
OutputStream generalOut = socket.getOutputStream();
// We want to write bytes, ints, Strings and objects of
// type Packet to the channel. The most appropriate filter
// stream is thus Object.
// Create the output stream first and flush it before
// creating the input stream, otherwise the input
// constructor may block (see API documentation). This is
// necessary only for Object streams and does not apply
// to, for example, Data streams.
// Don't forget to let the objects written to the stream
// implement java.io.Serializable.
out = new ObjectOutputStream(generalOut);
out.flush();
in = new ObjectInputStream(generalIn);
}
catch (Exception e) {
System.out.println("Channel: an error occurred while setting up the in/out streams.");
e.printStackTrace();
ChannelException ce = new ChannelException(e);
throw(ce);
}
}
public void sendObject (Object obj) throws ChannelException {
// This method sends the given message over the channel as a
// String. If there is a problem, e.g. if the connection is
// closed by the other side, a ChannelException is thrown.
if (debuggingMessages) {
System.out.println(" Channel: sending Object");
}
try {
out.writeObject(obj);
out.flush(); // Don't forget to flush the output stream after writing!
}
catch (Exception e) {
System.out.println("Channel: an error occurred while sending the message.");
e.printStackTrace();
ChannelException ce = new ChannelException(e);
throw(ce);
}
}
public Object receiveObject () throws ChannelException {
// This method waits for a message in the form of a String and
// returns it. If there is a problem, e.g. if the connection is
// closed by the other side, a ChannelException is thrown.
Object message = null;
if (debuggingMessages) {
System.out.println(" Channel: waiting for object...");
}
try {
message = in.readObject();
}
catch (Exception e) {
e.printStackTrace();
ChannelException ce = new ChannelException(e);
throw(ce);
}
if (debuggingMessages) {
System.out.println(" Channel: received Object");
}
return message;
}
public void close() throws ChannelException {
// This method closes the channel by closing the two in/out
// streams and the two sockets. If there is a problem, a
// ChannelException is thrown.
try {
in.close();
out.close();
socket.close();
}
catch (Exception e) {
System.out.println("Channel: an error occurred while closing the channel.");
e.printStackTrace();
ChannelException ce = new ChannelException(e);
throw(ce);
}
}
} |
Partager