1 |
/* ServerSocket.java -- Class for implementing server side sockets |
/* ServerSocket.java -- Class for implementing server side sockets |
2 |
Copyright (C) 1998,2000 Free Software Foundation, Inc. |
Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
28 |
|
|
29 |
import java.io.IOException; |
import java.io.IOException; |
30 |
|
|
31 |
/** |
/* Written using on-line Java Platform 1.2 API Specification. |
32 |
* This class models server side sockets. The basic model is that the |
* Status: I believe all methods are implemented. |
|
* server socket is created and bound to some well known port. It then |
|
|
* listens for and accepts connections. At that point the client and |
|
|
* server sockets are ready to communicate with one another utilizing |
|
|
* whatever application layer protocol they desire. |
|
|
* <p> |
|
|
* As with the <code>Socket</code> class, most instance methods of this class |
|
|
* simply redirect their calls to an implementation class. |
|
|
* |
|
|
* @author Aaron M. Renn (arenn@urbanophile.com) |
|
|
* @author Per Bothner <bothner@cygnus.com> |
|
|
*/ |
|
|
public class ServerSocket |
|
|
{ |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/* |
|
|
* Class Variables |
|
|
*/ |
|
|
|
|
|
/** |
|
|
* This is the user defined SocketImplFactory, if one is supplied |
|
|
*/ |
|
|
private static SocketImplFactory factory; |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/* |
|
|
* Instance Variables |
|
33 |
*/ |
*/ |
34 |
|
|
35 |
/** |
/** |
36 |
* This is the SocketImp object to which most instance methods in this |
* This class models server side sockets. The basic model is that the |
37 |
* class are redirected |
* server socket is created and bound to some well known port. It then |
38 |
*/ |
* listens for and accepts connections. At that point the client and |
39 |
private SocketImpl impl; |
* server sockets are ready to communicate with one another utilizing |
40 |
|
* whatever application layer protocol they desire. |
41 |
/*************************************************************************/ |
* <p> |
42 |
|
* As with the <code>Socket</code> class, most instance methods of this class |
43 |
/* |
* simply redirect their calls to an implementation class. |
44 |
* Class methods |
* |
45 |
|
* @author Aaron M. Renn (arenn@urbanophile.com) |
46 |
|
* @author Per Bothner (bothner@cygnus.com) |
47 |
*/ |
*/ |
48 |
|
public class ServerSocket |
|
/** |
|
|
* Sets the <code>SocketImplFactory</code> for all |
|
|
* <code>ServerSocket</code>'s. This may only be done |
|
|
* once per virtual machine. Subsequent attempts will generate an |
|
|
* exception. Note that a <code>SecurityManager</code> check is made prior to |
|
|
* setting the factory. If insufficient privileges exist to set the factory, |
|
|
* an exception will be thrown |
|
|
* |
|
|
* @exception SecurityException If this operation is not allowed by the |
|
|
* <code>SecurityManager</code>. |
|
|
* @exception SocketException If the factory object is already defined |
|
|
* @exception IOException If any other error occurs |
|
|
*/ |
|
|
public static synchronized void |
|
|
setSocketFactory(SocketImplFactory factory) throws IOException |
|
|
{ |
|
|
// See if already set |
|
|
if (ServerSocket.factory != null) |
|
|
throw new SocketException("SocketImplFactory already defined"); |
|
|
|
|
|
// Check permission to perform this operation |
|
|
SecurityManager sm = System.getSecurityManager(); |
|
|
if (sm != null) |
|
|
sm.checkSetFactory(); |
|
|
|
|
|
ServerSocket.factory = factory; |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* This constructor simply load the implementation and returns. |
|
|
*/ |
|
|
ServerSocket() |
|
|
{ |
|
|
if (factory != null) |
|
|
impl = factory.createSocketImpl(); |
|
|
else |
|
|
impl = new PlainSocketImpl(); |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* Creates a server socket and binds it to the specified port. If the |
|
|
* port number is 0, a random free port will be chosen. The pending |
|
|
* connection queue on this socket will be set to 50. |
|
|
* |
|
|
* @param port The port number to bind to |
|
|
* |
|
|
* @exception IOException If an error occurs |
|
|
*/ |
|
|
public |
|
|
ServerSocket(int port) throws IOException |
|
|
{ |
|
|
this(port, 50, null); |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* Creates a server socket and binds it to the specified port. If the |
|
|
* port number is 0, a random free port will be chosen. The pending |
|
|
* connection queue on this socket will be set to the value passed as |
|
|
* arg2. |
|
|
* |
|
|
* @param port The port number to bind to |
|
|
* @param queuelen The length of the pending connection queue |
|
|
* |
|
|
* @exception IOException If an error occurs |
|
|
*/ |
|
|
public |
|
|
ServerSocket(int port, int queuelen) throws IOException |
|
|
{ |
|
|
this(port, queuelen, null); |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* Creates a server socket and binds it to the specified port. If the |
|
|
* port number is 0, a random free port will be chosen. The pending |
|
|
* connection queue on this socket will be set to the value passed as |
|
|
* arg2. The third argument specifies a particular local address to |
|
|
* bind to. |
|
|
* |
|
|
* @param port The port number to bind to |
|
|
* @param queuelen The length of the pending connection queue |
|
|
* @param addr The address to bind to |
|
|
* |
|
|
* @exception IOException If an error occurs |
|
|
*/ |
|
|
public |
|
|
ServerSocket(int port, int queuelen, InetAddress addr) throws IOException |
|
|
{ |
|
|
this(); |
|
|
if (impl == null) |
|
|
throw new IOException("Cannot initialize Socket implementation"); |
|
|
|
|
|
SecurityManager sm = System.getSecurityManager(); |
|
|
if (sm != null) |
|
|
sm.checkListen(port); |
|
|
|
|
|
if (addr == null) |
|
|
addr = InetAddress.getInaddrAny(); |
|
|
|
|
|
impl.create(true); |
|
|
impl.bind(addr, port); |
|
|
impl.listen(queuelen); |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* This protected method is used to help subclasses override |
|
|
* <code>ServerSocket.accept()</code>. The passed in socket will be connected |
|
|
* when this method returns. |
|
|
* |
|
|
* @param socket The socket that is used for the accepted connection |
|
|
* |
|
|
* @exception IOException If an error occurs |
|
|
*/ |
|
|
protected final synchronized void |
|
|
implAccept(Socket socket) throws IOException |
|
|
{ |
|
|
impl.accept(socket.impl); |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* Accepts a new connection and returns a connected <code>Socket</code> |
|
|
* instance representing that connection. This method will block until a |
|
|
* connection is available. |
|
|
* |
|
|
* @exception IOException If an error occurs |
|
|
*/ |
|
|
public synchronized Socket |
|
|
accept() throws IOException |
|
|
{ |
|
|
Socket socket = new Socket(); |
|
|
impl.accept(socket.impl); |
|
|
|
|
|
return(socket); |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* Closes this socket and stops listening for connections |
|
|
* |
|
|
* @exception IOException If an error occurs |
|
|
*/ |
|
|
public synchronized void |
|
|
close() throws IOException |
|
|
{ |
|
|
impl.close(); |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* This method returns the local address to which this socket is bound |
|
|
* |
|
|
* @return The socket's local address |
|
|
*/ |
|
|
public InetAddress |
|
|
getInetAddress() |
|
|
{ |
|
|
return(impl.getInetAddress()); |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* This method returns the local port number to which this socket is bound |
|
|
* |
|
|
* @return The socket's port number |
|
|
*/ |
|
|
public int |
|
|
getLocalPort() |
|
|
{ |
|
|
return(impl.getLocalPort()); |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* Retrieves the current value of the SO_TIMEOUT setting. A value of 0 |
|
|
* implies that SO_TIMEOUT is disabled (ie, operations never time out). |
|
|
* This is the number of milliseconds a socket operation can block before |
|
|
* an InterruptedIOException is thrown. |
|
|
* |
|
|
* @return The value of SO_TIMEOUT |
|
|
* |
|
|
* @exception IOException If an error occurs |
|
|
*/ |
|
|
public synchronized int |
|
|
getSoTimeout() throws IOException |
|
|
{ |
|
|
Object obj = impl.getOption(SocketOptions.SO_TIMEOUT); |
|
|
|
|
|
if (!(obj instanceof Integer)) |
|
|
throw new IOException("Internal Error"); |
|
|
|
|
|
return(((Integer)obj).intValue()); |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* Sets the value of SO_TIMEOUT. A value of 0 implies that SO_TIMEOUT is |
|
|
* disabled (ie, operations never time out). This is the number of |
|
|
* milliseconds a socket operation can block before an |
|
|
* InterruptedIOException is thrown. |
|
|
* |
|
|
* @param timeout The new SO_TIMEOUT value |
|
|
* |
|
|
* @exception IOException If an error occurs |
|
|
*/ |
|
|
public synchronized void |
|
|
setSoTimeout(int timeout) throws IOException |
|
49 |
{ |
{ |
|
if (timeout < 0) |
|
|
throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0"); |
|
|
|
|
|
impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout)); |
|
|
} |
|
50 |
|
|
51 |
/*************************************************************************/ |
// Class Variables |
52 |
|
|
53 |
/** |
/** |
54 |
* Returns the value of this socket as a <code>String</code>. |
* This is the user defined SocketImplFactory, if one is supplied |
55 |
* |
*/ |
56 |
* @return This socket represented as a <code>String</code>. |
private static SocketImplFactory factory; |
57 |
*/ |
|
58 |
public String |
// Instance Variables |
59 |
toString() |
|
60 |
{ |
/** |
61 |
return("Server Socket " + impl.toString()); |
* This is the SocketImp object to which most instance methods in this |
62 |
|
* class are redirected |
63 |
|
*/ |
64 |
|
private SocketImpl impl; |
65 |
|
|
66 |
|
/** |
67 |
|
* Private constructor that simply sets the implementation. |
68 |
|
*/ |
69 |
|
private ServerSocket() |
70 |
|
{ |
71 |
|
if (factory != null) |
72 |
|
impl = factory.createSocketImpl(); |
73 |
|
else |
74 |
|
impl = new PlainSocketImpl(); |
75 |
|
} |
76 |
|
|
77 |
|
/** |
78 |
|
* Creates a server socket and binds it to the specified port. If the |
79 |
|
* port number is 0, a random free port will be chosen. The pending |
80 |
|
* connection queue on this socket will be set to 50. |
81 |
|
* |
82 |
|
* @param port The port number to bind to |
83 |
|
* |
84 |
|
* @exception IOException If an error occurs |
85 |
|
*/ |
86 |
|
public ServerSocket (int port) |
87 |
|
throws java.io.IOException |
88 |
|
{ |
89 |
|
this(port, 50); |
90 |
|
} |
91 |
|
|
92 |
|
/** |
93 |
|
* Creates a server socket and binds it to the specified port. If the |
94 |
|
* port number is 0, a random free port will be chosen. The pending |
95 |
|
* connection queue on this socket will be set to the value passed as |
96 |
|
* arg2. |
97 |
|
* |
98 |
|
* @param port The port number to bind to |
99 |
|
* @param backlog The length of the pending connection queue |
100 |
|
* |
101 |
|
* @exception IOException If an error occurs |
102 |
|
*/ |
103 |
|
public ServerSocket (int port, int backlog) |
104 |
|
throws java.io.IOException |
105 |
|
{ |
106 |
|
this(port, backlog, null); |
107 |
|
} |
108 |
|
|
109 |
|
/** |
110 |
|
* Creates a server socket and binds it to the specified port. If the |
111 |
|
* port number is 0, a random free port will be chosen. The pending |
112 |
|
* connection queue on this socket will be set to the value passed as |
113 |
|
* backlog. The third argument specifies a particular local address to |
114 |
|
* bind t or null to bind to all local address. |
115 |
|
* |
116 |
|
* @param port The port number to bind to |
117 |
|
* @param backlog The length of the pending connection queue |
118 |
|
* @param bindAddr The address to bind to, or null to bind to all addresses |
119 |
|
* |
120 |
|
* @exception IOException If an error occurs |
121 |
|
*/ |
122 |
|
public ServerSocket (int port, int backlog, InetAddress bindAddr) |
123 |
|
throws java.io.IOException |
124 |
|
{ |
125 |
|
this(); |
126 |
|
if (impl == null) |
127 |
|
throw new IOException("Cannot initialize Socket implementation"); |
128 |
|
|
129 |
|
SecurityManager s = System.getSecurityManager(); |
130 |
|
if (s != null) |
131 |
|
s.checkListen(port); |
132 |
|
|
133 |
|
if (bindAddr == null) |
134 |
|
bindAddr = InetAddress.ANY_IF; |
135 |
|
|
136 |
|
impl.create(true); |
137 |
|
impl.bind(bindAddr, port); |
138 |
|
impl.listen(backlog); |
139 |
|
} |
140 |
|
|
141 |
|
/** |
142 |
|
* This method returns the local address to which this socket is bound |
143 |
|
* |
144 |
|
* @return The socket's local address |
145 |
|
*/ |
146 |
|
public InetAddress getInetAddress() |
147 |
|
{ |
148 |
|
return impl.getInetAddress(); |
149 |
|
} |
150 |
|
|
151 |
|
/** |
152 |
|
* This method returns the local port number to which this socket is bound |
153 |
|
* |
154 |
|
* @return The socket's port number |
155 |
|
*/ |
156 |
|
public int getLocalPort() |
157 |
|
{ |
158 |
|
return impl.getLocalPort(); |
159 |
|
} |
160 |
|
|
161 |
|
/** |
162 |
|
* Accepts a new connection and returns a connected <code>Socket</code> |
163 |
|
* instance representing that connection. This method will block until a |
164 |
|
* connection is available. |
165 |
|
* |
166 |
|
* @exception IOException If an error occurs |
167 |
|
*/ |
168 |
|
public Socket accept () throws IOException |
169 |
|
{ |
170 |
|
Socket s = new Socket(); |
171 |
|
implAccept (s); |
172 |
|
|
173 |
|
return s; |
174 |
|
} |
175 |
|
|
176 |
|
/** |
177 |
|
* This protected method is used to help subclasses override |
178 |
|
* <code>ServerSocket.accept()</code>. The passed in socket will be |
179 |
|
* connected when this method returns. |
180 |
|
* |
181 |
|
* @param socket The socket that is used for the accepted connection |
182 |
|
* |
183 |
|
* @exception IOException If an error occurs |
184 |
|
*/ |
185 |
|
protected final void implAccept (Socket s) throws IOException |
186 |
|
{ |
187 |
|
impl.accept(s.impl); |
188 |
|
} |
189 |
|
|
190 |
|
/** |
191 |
|
* Closes this socket and stops listening for connections |
192 |
|
* |
193 |
|
* @exception IOException If an error occurs |
194 |
|
*/ |
195 |
|
public void close () throws IOException |
196 |
|
{ |
197 |
|
impl.close(); |
198 |
|
} |
199 |
|
|
200 |
|
/** |
201 |
|
* Sets the value of SO_TIMEOUT. A value of 0 implies that SO_TIMEOUT is |
202 |
|
* disabled (ie, operations never time out). This is the number of |
203 |
|
* milliseconds a socket operation can block before an |
204 |
|
* InterruptedIOException is thrown. |
205 |
|
* |
206 |
|
* @param timeout The new SO_TIMEOUT value |
207 |
|
* |
208 |
|
* @exception IOException If an error occurs |
209 |
|
*/ |
210 |
|
public void setSoTimeout (int timeout) throws SocketException |
211 |
|
{ |
212 |
|
if (timeout < 0) |
213 |
|
throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0"); |
214 |
|
|
215 |
|
impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout)); |
216 |
|
} |
217 |
|
|
218 |
|
/** |
219 |
|
* Retrieves the current value of the SO_TIMEOUT setting. A value of 0 |
220 |
|
* implies that SO_TIMEOUT is disabled (ie, operations never time out). |
221 |
|
* This is the number of milliseconds a socket operation can block before |
222 |
|
* an InterruptedIOException is thrown. |
223 |
|
* |
224 |
|
* @return The value of SO_TIMEOUT |
225 |
|
* |
226 |
|
* @exception IOException If an error occurs |
227 |
|
*/ |
228 |
|
public int getSoTimeout () throws IOException |
229 |
|
{ |
230 |
|
Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT); |
231 |
|
|
232 |
|
if (!(timeout instanceof Integer)) |
233 |
|
throw new IOException("Internal Error"); |
234 |
|
|
235 |
|
return ((Integer)timeout).intValue(); |
236 |
|
} |
237 |
|
|
238 |
|
/** |
239 |
|
* Returns the value of this socket as a <code>String</code>. |
240 |
|
* |
241 |
|
* @return This socket represented as a <code>String</code>. |
242 |
|
*/ |
243 |
|
public String toString () |
244 |
|
{ |
245 |
|
return "ServerSocket " + impl.toString(); |
246 |
|
} |
247 |
|
|
248 |
|
// Class methods |
249 |
|
|
250 |
|
/** |
251 |
|
* Sets the <code>SocketImplFactory</code> for all |
252 |
|
* <code>ServerSocket</code>'s. This may only be done |
253 |
|
* once per virtual machine. Subsequent attempts will generate an |
254 |
|
* exception. Note that a <code>SecurityManager</code> check is made prior |
255 |
|
* to setting the factory. If insufficient privileges exist to set the |
256 |
|
* factory, an exception will be thrown |
257 |
|
* |
258 |
|
* @exception SecurityException If this operation is not allowed by the |
259 |
|
* <code>SecurityManager</code>. |
260 |
|
* @exception SocketException If the factory object is already defined |
261 |
|
* @exception IOException If any other error occurs |
262 |
|
*/ |
263 |
|
public static synchronized void setSocketFactory (SocketImplFactory fac) |
264 |
|
throws IOException |
265 |
|
{ |
266 |
|
factory = fac; |
267 |
|
} |
268 |
} |
} |
|
|
|
|
} // class ServerSocket |
|
|
|
|