001: package net.matuschek.util;
002:
003: import java.io.IOException;
004: import java.io.InterruptedIOException;
005: import java.net.InetAddress;
006: import java.net.Socket;
007:
008: /**
009: * This class offers a timeout feature on socket connections.
010: * A maximum length of time allowed for a connection can be
011: * specified, along with a host and port.
012: *
013: * @author David Reilly (written for JavaWorld)
014: * @author Daniel Matuschek
015: * @version $Id: TimedSocket.java,v 1.2 2002/05/31 14:45:56 matuschd Exp $
016: *
017: * imported to the net.matuschek.util source tree by Daniel Matuschek
018: */
019: public class TimedSocket {
020:
021: /**
022: * Attempts to connect to a service at the specified address
023: * and port, for a specified maximum amount of time.
024: *
025: * @param addr Address of host
026: * @param port Port of service
027: * @param delay Delay in milliseconds
028: */
029: public static Socket getSocket(InetAddress addr, int port, int delay)
030: throws InterruptedIOException, IOException {
031: // Create a new socket thread, and start it running
032: SocketThread st = new SocketThread(addr, port);
033: st.start();
034:
035: int timer = 0;
036: Socket sock = null;
037:
038: for (;;) {
039: // Check to see if a connection is established
040:
041: if (st.isConnected()) {
042: // Yes ... assign to sock variable, and break out of loop
043: sock = st.getSocket();
044: break;
045: } else {
046: // Check to see if an error occurred
047: if (st.isError()) {
048: // No connection could be established
049: throw (st.getException());
050: }
051:
052: try {
053: // Sleep for a short period of time
054: Thread.sleep(POLL_DELAY);
055: } catch (InterruptedException ie) {
056: }
057:
058: // Increment timer
059: timer += POLL_DELAY;
060:
061: // Check to see if time limit exceeded
062: if (timer > delay) {
063: // Can't connect to server
064: throw new InterruptedIOException(
065: "Could not connect for " + delay
066: + " milliseconds");
067: }
068: }
069: }
070:
071: return sock;
072: }
073:
074: /**
075: * Attempts to connect to a service at the specified address
076: * and port, for a specified maximum amount of time.
077: *
078: * @param host Hostname of machine
079: * @param port Port of service
080: * @param delay Delay in milliseconds
081: */
082: public static Socket getSocket(String host, int port, int delay)
083: throws InterruptedIOException, IOException {
084: // Convert host into an InetAddress, and call getSocket method
085: InetAddress inetAddr = InetAddress.getByName(host);
086:
087: return getSocket(inetAddr, port, delay);
088: }
089:
090: /**
091: * Inner class for establishing a socket thread
092: * within another thread, to prevent blocking.
093: */
094: static class SocketThread extends Thread {
095: // Socket connection to remote host
096: volatile private Socket m_connection = null;
097: // Hostname to connect to
098: private String m_host = null;
099: // Internet Address to connect to
100: private InetAddress m_inet = null;
101: // Port number to connect to
102: private int m_port = 0;
103: // Exception in the event a connection error occurs
104: private IOException m_exception = null;
105:
106: // Connect to the specified host and port number
107: public SocketThread(String host, int port) {
108: // Assign to member variables
109: m_host = host;
110: m_port = port;
111: }
112:
113: // Connect to the specified host IP and port number
114: public SocketThread(InetAddress inetAddr, int port) {
115: // Assign to member variables
116: m_inet = inetAddr;
117: m_port = port;
118: }
119:
120: public void run() {
121: // Socket used for establishing a connection
122: Socket sock = null;
123:
124: try {
125: // Was a string or an inet specified
126: if (m_host != null) {
127: // Connect to a remote host - BLOCKING I/O
128: sock = new Socket(m_host, m_port);
129: } else {
130: // Connect to a remote host - BLOCKING I/O
131: sock = new Socket(m_inet, m_port);
132: }
133: } catch (IOException ioe) {
134: // Assign to our exception member variable
135: m_exception = ioe;
136: return;
137: }
138:
139: // If socket constructor returned without error,
140: // then connection finished
141: m_connection = sock;
142: }
143:
144: // Are we connected?
145: public boolean isConnected() {
146: if (m_connection == null)
147: return false;
148: else
149: return true;
150: }
151:
152: // Did an error occur?
153: public boolean isError() {
154: if (m_exception == null)
155: return false;
156: else
157: return true;
158: }
159:
160: // Get socket
161: public Socket getSocket() {
162: return m_connection;
163: }
164:
165: // Get exception
166: public IOException getException() {
167: return m_exception;
168: }
169: }
170:
171: /** Polling delay for socket checks (in milliseconds) */
172: private static final int POLL_DELAY = 100;
173: }
|