OSDN Git Service

2003-05-02 Michael Koch <konqueror@gmx.de>
[pf3gnuchains/gcc-fork.git] / libjava / java / net / ServerSocket.java
1 /* ServerSocket.java -- Class for implementing server side sockets
2    Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10  
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 package java.net;
39
40 import java.io.IOException;
41 import java.nio.channels.IllegalBlockingModeException;
42 import java.nio.channels.ServerSocketChannel;
43
44 /* Written using on-line Java Platform 1.2 API Specification.
45  * Status:  I believe all methods are implemented.
46  */
47
48 /**
49  * This class models server side sockets.  The basic model is that the
50  * server socket is created and bound to some well known port.  It then
51  * listens for and accepts connections.  At that point the client and
52  * server sockets are ready to communicate with one another utilizing
53  * whatever application layer protocol they desire.
54  *
55  * As with the <code>Socket</code> class, most instance methods of this class 
56  * simply redirect their calls to an implementation class.
57  *
58  * @author Aaron M. Renn (arenn@urbanophile.com)
59  * @author Per Bothner (bothner@cygnus.com)
60  */
61 public class ServerSocket
62 {
63   /**
64    * This is the user defined SocketImplFactory, if one is supplied
65    */
66   private static SocketImplFactory factory;
67
68   /**
69    * This is the SocketImp object to which most instance methods in this
70    * class are redirected
71    */
72   private SocketImpl impl;
73
74   /**
75    * ServerSocketChannel of this ServerSocket. This channel only exists
76    * when the socket is created by ServerSocketChannel.open().
77    */
78   private ServerSocketChannel ch;
79
80   private boolean closed = false;
81   
82   /**
83    * Constructor that simply sets the implementation.
84    * 
85    * @exception IOException If an error occurs
86    *
87    * @specnote This constructor is public since JDK 1.4
88    */
89   public ServerSocket() throws IOException
90   {
91     if (factory != null)
92       impl = factory.createSocketImpl();
93     else
94       impl = new PlainSocketImpl();
95
96     impl.create(true);
97   }
98
99   /**
100    * Creates a server socket and binds it to the specified port.  If the
101    * port number is 0, a random free port will be chosen.  The pending
102    * connection queue on this socket will be set to 50.
103    *
104    * @param port The port number to bind to
105    * 
106    * @exception IOException If an error occurs
107    * @exception SecurityException If a security manager exists and its
108    * checkListen method doesn't allow the operation
109    */
110   public ServerSocket (int port)
111     throws IOException
112   {
113     this(port, 50);
114   }
115
116   /**
117    * Creates a server socket and binds it to the specified port.  If the
118    * port number is 0, a random free port will be chosen.  The pending
119    * connection queue on this socket will be set to the value passed as
120    * arg2.
121    *
122    * @param port The port number to bind to
123    * @param backlog The length of the pending connection queue
124    *
125    * @exception IOException If an error occurs
126    * @exception SecurityException If a security manager exists and its
127    * checkListen method doesn't allow the operation
128    */
129   public ServerSocket (int port, int backlog)
130     throws IOException
131   {
132     this(port, backlog, null);
133   }
134
135   /**
136    * Creates a server socket and binds it to the specified port.  If the
137    * port number is 0, a random free port will be chosen.  The pending
138    * connection queue on this socket will be set to the value passed as
139    * backlog.  The third argument specifies a particular local address to
140    * bind t or null to bind to all local address.
141    *
142    * @param port The port number to bind to
143    * @param backlog The length of the pending connection queue
144    * @param bindAddr The address to bind to, or null to bind to all addresses
145    *
146    * @exception IOException If an error occurs
147    * @exception SecurityException If a security manager exists and its
148    * checkListen method doesn't allow the operation
149    *
150    * @since 1.1
151    */
152   public ServerSocket (int port, int backlog, InetAddress bindAddr)
153     throws IOException
154   {
155     this();
156
157     if (impl == null)
158       throw new IOException("Cannot initialize Socket implementation");
159
160     SecurityManager s = System.getSecurityManager();
161     if (s != null)
162       s.checkListen(port);
163
164     if (bindAddr == null)
165       bindAddr = InetAddress.ANY_IF;
166
167     // create socket
168     impl.create(true);
169
170     // bind to address/port
171     try
172       {
173         impl.bind(bindAddr, port);
174       }
175     catch (IOException exception)
176       {
177         impl.close();
178         throw exception;
179       }
180     catch (RuntimeException exception)
181       {
182         impl.close();
183         throw exception;
184       }
185     catch (Error error)
186       {
187         impl.close();
188         throw error;
189       }
190
191     // listen on socket
192     try
193       {
194         impl.listen(backlog);
195       }
196     catch (IOException exception)
197       {
198         impl.close();
199         throw exception;
200       }
201     catch (RuntimeException exception)
202       {
203         impl.close();
204         throw exception;
205       }
206     catch (Error error)
207       {
208         impl.close();
209         throw error;
210       }
211   }
212
213   /**
214    * Binds the server socket to a specified socket address
215    *
216    * @param endpoint The socket address to bind to
217    *
218    * @exception IOException If an error occurs
219    * @exception IllegalArgumentException If address type is not supported
220    * @exception SecurityException If a security manager exists and its
221    * checkListen method doesn't allow the operation
222    * 
223    * @since 1.4
224    */
225   public void bind (SocketAddress endpoint)
226     throws IOException
227   {
228     bind (endpoint, 50);
229   }
230  
231   /**
232    * Binds the server socket to a specified socket address
233    *
234    * @param endpoint The socket address to bind to
235    * @param backlog The length of the pending connection queue
236    * 
237    * @exception IOException If an error occurs
238    * @exception IllegalArgumentException If address type is not supported
239    * @exception SecurityException If a security manager exists and its
240    * checkListen method doesn't allow the operation
241    *
242    * @since 1.4
243    */
244   public void bind (SocketAddress endpoint, int backlog) throws IOException
245   {
246     if (closed)
247       throw new SocketException ("ServerSocket is closed");
248     
249     if (impl == null)
250       throw new IOException ("Cannot initialize Socket implementation");
251
252     if (! (endpoint instanceof InetSocketAddress))
253       throw new IllegalArgumentException ("Address type not supported");
254
255     InetSocketAddress tmp = (InetSocketAddress) endpoint;
256     
257     SecurityManager s = System.getSecurityManager ();
258     if (s != null)
259       s.checkListen (tmp.getPort ());
260
261     impl.bind (tmp.getAddress (), tmp.getPort ());
262     impl.listen(backlog);
263   }
264   
265   /**
266    * This method returns the local address to which this socket is bound
267    *
268    * @return The socket's local address
269    */
270   public InetAddress getInetAddress()
271   {
272     try
273       {
274         return (InetAddress) impl.getOption (SocketOptions.SO_BINDADDR);
275       }
276     catch (SocketException e)
277       {
278         return null;
279       }
280   }
281
282   /**
283    * This method returns the local port number to which this socket is bound
284    *
285    * @return The socket's port number
286    */
287   public int getLocalPort()
288   {
289     return impl.getLocalPort();
290   }
291
292   /**
293    * Returns the local socket address
294    *
295    * @since 1.4
296    */
297   public SocketAddress getLocalSocketAddress()
298   {
299     InetAddress addr = getInetAddress();
300
301     if (addr != null)
302       return new InetSocketAddress (getInetAddress(), getLocalPort());
303
304     return null;
305   }
306
307   /**
308    * Accepts a new connection and returns a connected <code>Socket</code> 
309    * instance representing that connection.  This method will block until a 
310    * connection is available.
311    *
312    * @exception IOException If an error occurs
313    * @exception SecurityException If a security manager exists and its
314    * checkListen method doesn't allow the operation
315    * @exception IllegalBlockingModeException If this socket has an associated
316    * channel, and the channel is in non-blocking mode
317    * @exception SocketTimeoutException If a timeout was previously set with
318    * setSoTimeout and the timeout has been reached
319    */
320   public Socket accept () throws IOException
321   {
322     if (impl == null)
323       throw new IOException ("Cannot initialize Socket implementation");
324
325     SecurityManager sm = System.getSecurityManager ();
326     if (sm != null)
327       sm.checkListen (impl.getLocalPort ());
328
329     Socket s = new Socket();
330     implAccept (s);
331
332     return s;
333   }
334
335   /**
336    * This protected method is used to help subclasses override 
337    * <code>ServerSocket.accept()</code>.  The passed in socket will be
338    * connected when this method returns.
339    *
340    * @param socket The socket that is used for the accepted connection
341    *
342    * @exception IOException If an error occurs
343    * @exception IllegalBlockingModeException If this socket has an associated
344    * channel, and the channel is in non-blocking mode
345    *
346    * @since 1.1
347    */
348   protected final void implAccept (Socket s)
349     throws IOException
350   {
351     if (ch != null && !ch.isBlocking())
352       throw new IllegalBlockingModeException();
353             
354     impl.accept(s.impl);
355   }
356
357   /**
358    * Closes this socket and stops listening for connections
359    *
360    * @exception IOException If an error occurs
361    */
362   public void close () throws IOException
363   {
364     if (impl != null)
365       impl.close ();
366
367     if (ch != null)
368       ch.close ();
369     
370     closed = true;
371   }
372
373   /**
374    * Returns the unique ServerSocketChannel object
375    * associated with this socket, if any.
376    *
377    * The socket only has a ServerSocketChannel if its created
378    * by ServerSocketChannel.open.
379    * 
380    * @since 1.4
381    */
382   public ServerSocketChannel getChannel()
383   {
384     return ch;
385   }
386
387   /**
388    * Returns true then the socket is bound, otherwise false
389    * 
390    * @since 1.4
391    */
392   public boolean isBound()
393   {
394     try
395       {
396         Object bindaddr = impl.getOption (SocketOptions.SO_BINDADDR);
397       }
398     catch (SocketException e)
399       {
400         return false;
401       }
402     
403     return true;
404   }
405
406   /**
407    * Returns true if the socket is closed, otherwise false
408    * 
409    * @since 1.4
410    */
411   public boolean isClosed()
412   {
413     return closed;
414   }
415
416   /**
417    * Sets the value of SO_TIMEOUT.  A value of 0 implies that SO_TIMEOUT is
418    * disabled (ie, operations never time out).  This is the number of 
419    * milliseconds a socket operation can block before an
420    * InterruptedIOException is thrown.
421    *
422    * @param timeout The new SO_TIMEOUT value
423    *
424    * @exception SocketException If an error occurs
425    *
426    * @since 1.1
427    */
428   public void setSoTimeout (int timeout) throws SocketException
429   {
430     if (timeout < 0)
431       throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0");
432
433     impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
434   }
435
436   /**
437    * Retrieves the current value of the SO_TIMEOUT setting.  A value of 0
438    * implies that SO_TIMEOUT is disabled (ie, operations never time out).
439    * This is the number of milliseconds a socket operation can block before
440    * an InterruptedIOException is thrown.
441    *
442    * @return The value of SO_TIMEOUT
443    *
444    * @exception IOException If an error occurs
445    *
446    * @since 1.1
447    */
448   public int getSoTimeout () throws IOException
449   {
450     Object timeout = impl.getOption(SocketOptions.SO_TIMEOUT);
451
452     if (!(timeout instanceof Integer))
453       throw new IOException("Internal Error");
454
455     return ((Integer)timeout).intValue();
456   }
457
458   /**
459    * Enables/Disables the SO_REUSEADDR option
460    * 
461    * @exception SocketException If an error occurs
462    * 
463    * @since 1.4
464    */
465   public void setReuseAddress (boolean on)
466     throws SocketException
467   {
468     if (impl == null)
469       throw new SocketException ("Cannot initialize Socket implementation");
470
471     impl.setOption (SocketOptions.SO_REUSEADDR, new Boolean (on));
472   }
473
474   /**
475    * Checks if the SO_REUSEADDR option is enabled
476    * 
477    * @exception SocketException If an error occurs
478    * 
479    * @since 1.4
480    */
481   public boolean getReuseAddress()
482     throws SocketException
483   {
484     if (impl == null)
485       throw new SocketException ("Cannot initialize Socket implementation");
486
487     Object reuseaddr = impl.getOption (SocketOptions.SO_REUSEADDR);
488
489     if (!(reuseaddr instanceof Boolean))
490       throw new SocketException ("Internal Error");
491     
492     return ((Boolean) reuseaddr).booleanValue ();
493   }
494
495   /**
496    * This method sets the value for the system level socket option
497    * SO_RCVBUF to the specified value.  Note that valid values for this
498    * option are specific to a given operating system.
499    * 
500    * @param size The new receive buffer size.
501    * 
502    * @exception SocketException If an error occurs or Socket is not connected
503    * @exception IllegalArgumentException If size is 0 or negative
504    *
505    * @since 1.4
506    */
507   public void setReceiveBufferSize (int size)
508     throws SocketException
509   {
510     if (impl == null)
511       throw new SocketException ("Not connected");
512
513     if (size <= 0)
514       throw new IllegalArgumentException ("SO_RCVBUF value must be > 0");
515
516     impl.setOption (SocketOptions.SO_RCVBUF, new Integer (size));
517   }
518
519   /**
520    * This method returns the value of the system level socket option
521    * SO_RCVBUF, which is used by the operating system to tune buffer
522    * sizes for data transfers.
523    * 
524    * @return The receive buffer size.
525    *             
526    * @exception SocketException If an error occurs or Socket is not connected
527    * 
528    * @since 1.4
529    */
530   public int getReceiveBufferSize ()
531     throws SocketException
532   {
533     if (impl == null)
534       throw new SocketException ("Not connected");
535
536     Object buf = impl.getOption (SocketOptions.SO_RCVBUF);
537
538     if (!(buf instanceof Integer))
539       throw new SocketException ("Internal Error: Unexpected type");
540     
541     return ((Integer) buf).intValue ();
542   }
543
544   /**
545    * Returns the value of this socket as a <code>String</code>. 
546    *
547    * @return This socket represented as a <code>String</code>.
548    */
549   public String toString ()
550   {
551     return "ServerSocket" + impl.toString();
552   }
553
554   // Class methods
555
556   /**
557    * Sets the <code>SocketImplFactory</code> for all 
558    * <code>ServerSocket</code>'s.  This may only be done
559    * once per virtual machine.  Subsequent attempts will generate an
560    * exception.  Note that a <code>SecurityManager</code> check is made prior
561    * to setting the factory.  If insufficient privileges exist to set the
562    * factory, an exception will be thrown
563    *
564    * @exception SecurityException If this operation is not allowed by the
565    * <code>SecurityManager</code>.
566    * @exception SocketException If the factory object is already defined
567    * @exception IOException If any other error occurs
568    */
569   public static synchronized void setSocketFactory (SocketImplFactory fac)
570     throws IOException
571   {
572     factory = fac;
573   }
574 }