001: /*
002: * Copyright (c) 2000 by Matt Welsh and The Regents of the University of
003: * California. All rights reserved.
004: *
005: * Permission to use, copy, modify, and distribute this software and its
006: * documentation for any purpose, without fee, and without written agreement is
007: * hereby granted, provided that the above copyright notice and the following
008: * two paragraphs appear in all copies of this software.
009: *
010: * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
011: * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
012: * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
013: * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
014: *
015: * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
016: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
017: * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
018: * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
019: * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
020: *
021: * Author: Matt Welsh <mdw@cs.berkeley.edu>
022: *
023: */
024:
025: package seda.nbio;
026:
027: import java.io.*;
028: import java.net.*;
029:
030: /**
031: * A NonblockingServerSocket implements a nonblocking variant of
032: * java.net.ServerSocket. (Ideally it would simply extend the latter
033: * class, but ServerSocket does not contain an appropriate public
034: * constructor which would make that feasible.)
035: *
036: * @see java.net.ServerSocket
037: */
038: public class NonblockingServerSocket implements Selectable {
039:
040: private static final boolean DEBUG = false;
041:
042: // Default value stolen from Apache :-)
043: private static final int DEFAULT_LISTEN_BACKLOG = 511;
044:
045: static {
046: NonblockingSocket.loadNativeLibrary();
047: }
048:
049: NonblockingSocketImpl impl;
050:
051: private NonblockingSocket accept_tmp = null;
052:
053: /**
054: * Create a nonblocking server socket listening on the given port.
055: */
056: public NonblockingServerSocket(int port) throws IOException {
057: this (port, DEFAULT_LISTEN_BACKLOG, null);
058: }
059:
060: /**
061: * Create a nonblocking server socket listening on the given port with
062: * the given connection backlog (the default is 511).
063: */
064: public NonblockingServerSocket(int port, int backlog)
065: throws IOException {
066: this (port, backlog, null);
067: }
068:
069: /**
070: * Create a nonblocking server socket listening on the given port,
071: * with the given connection backlog, bound to the given address.
072: * This is useful if you wish to bind the socket to an address other
073: * than INADDR_ANY.
074: */
075: public NonblockingServerSocket(int port, int backlog,
076: InetAddress bindAddr) throws IOException {
077: impl = new NonblockingSocketImpl();
078:
079: if (port < 0 || port > 0xFFFF) {
080: throw new IllegalArgumentException("port out range:" + port);
081: }
082:
083: try {
084: if (DEBUG)
085: System.err.println("NonblockingServerSocket (port "
086: + port + "): Calling create");
087: impl.create(true);
088: if (DEBUG)
089: System.err.println("NonblockingServerSocket (port "
090: + port + "): Calling bind");
091: impl.bind(bindAddr, port);
092: if (DEBUG)
093: System.err.println("NonblockingServerSocket (port "
094: + port + "): Calling listen");
095: impl.listen(backlog);
096: } catch (IOException e) {
097: impl.close();
098: throw e;
099: }
100: if (DEBUG)
101: System.err.println("NonblockingServerSocket (port " + port
102: + "): Returning from constructor");
103: }
104:
105: /**
106: * Accept a connection on this server socket. This is a <b>blocking</b>
107: * operation.
108: *
109: * @return A NonblockingSocket corresponding to the new connection.
110: */
111: public NonblockingSocket accept() throws IOException {
112: NonblockingSocket s = new NonblockingSocket();
113: if (DEBUG)
114: System.err
115: .println("NonblockingServerSocket: Calling blocking accept");
116: impl.accept(s.impl);
117: if (DEBUG)
118: System.err
119: .println("NonblockingServerSocket: Returned from blocking accept");
120: return s;
121: }
122:
123: /**
124: * Perform a nonblocking accept() on this socket. Returns null if no
125: * connection was established. Selecting this socket for ACCEPT_READY
126: * will allow you to determine if nbAccept() will return a new connection.
127: *
128: * @see SelectSet
129: */
130: public synchronized NonblockingSocket nbAccept() throws IOException {
131: if (DEBUG)
132: System.err
133: .println("NonblockingServerSocket: Calling nonblocking accept");
134: if (accept_tmp == null)
135: accept_tmp = new NonblockingSocket();
136: if (impl.nbAccept(accept_tmp.impl) < 0) {
137: if (DEBUG)
138: System.err
139: .println("NonblockingServerSocket: Nonblocking accept returning null");
140: return null;
141: } else {
142: NonblockingSocket tmp = accept_tmp;
143: accept_tmp = null;
144: if (DEBUG)
145: System.err
146: .println("NonblockingServerSocket: Nonblocking accept returning "
147: + tmp);
148: return tmp;
149: }
150: }
151:
152: /**
153: * Return the address to which this socket is bound.
154: */
155: public InetAddress getInetAddress() {
156: return impl.getInetAddress();
157: }
158:
159: /**
160: * Return the port to which this socket is bound.
161: */
162: public int getLocalPort() {
163: return impl.getLocalPort();
164: }
165:
166: /**
167: * Currently unimplemented.
168: */
169: public synchronized void setSoTimeout(int timeout)
170: throws SocketException {
171: // XXX MDW Do nothing
172: }
173:
174: /**
175: * Currently unimplemented.
176: */
177: public synchronized int getSoTimeout() throws SocketException {
178: // XXX MDW Do nothing
179: return 0;
180: }
181:
182: /**
183: * Close the socket.
184: */
185: public synchronized void close() throws IOException {
186: impl.close();
187: }
188:
189: public String toString() {
190: String s;
191: try {
192: s = impl.getInetAddress().getHostAddress();
193: } catch (NullPointerException e) {
194: s = "<none>";
195: }
196: return "NonblockingServerSocket[addr=" + s + ",localport="
197: + impl.getLocalPort() + "]";
198: }
199:
200: }
|