1 /* Socket.java -- Client socket implementation
2 Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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)
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.
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
21 As a special exception, if you link this library with other files to
22 produce an executable, this library does not by itself cause the
23 resulting executable to be covered by the GNU General Public License.
24 This exception does not however invalidate any other reasons why the
25 executable file might be covered by the GNU General Public License. */
31 /* Written using on-line Java Platform 1.2 API Specification.
32 * Status: I believe all methods are implemented.
36 * This class models a client site socket. A socket is a TCP/IP endpoint
37 * for network communications conceptually similar to a file handle.
39 * This class does not actually do any work. Instead, it redirects all of
40 * its calls to a socket implementation object which implements the
41 * <code>SocketImpl</code> interface. The implementation class is
42 * instantiated by factory class that implements the
43 * <code>SocketImplFactory interface</code>. A default
44 * factory is provided, however the factory may be set by a call to
45 * the <code>setSocketImplFactory</code> method. Note that this may only be
46 * done once per virtual machine. If a subsequent attempt is made to set the
47 * factory, a <code>SocketException</code> will be thrown.
49 * @author Aaron M. Renn (arenn@urbanophile.com)
50 * @author Per Bothner (bothner@cygnus.com)
58 * This is the user SocketImplFactory for this class. If this variable is
59 * null, a default factory is used.
61 static SocketImplFactory factory
;
66 * The implementation object to which calls are redirected
73 * Initializes a new instance of <code>Socket</code> object without
74 * connecting to a remote host. This useful for subclasses of socket that
75 * might want this behavior.
80 impl
= factory
.createSocketImpl();
82 impl
= new PlainSocketImpl();
86 * Initializes a new instance of <code>Socket</code> object without
87 * connecting to a remote host. This is useful for subclasses of socket
88 * that might want this behavior.
90 * Additionally, this socket will be created using the supplied
91 * implementation class instead the default class or one returned by a
92 * factory. This value can be <code>null</code>, but if it is, all instance
93 * methods in <code>Socket</code> should be overridden because most of them
94 * rely on this value being populated.
96 * @param impl The <code>SocketImpl</code> to use for this
99 * @exception SocketException If an error occurs
101 protected Socket (SocketImpl impl
) throws SocketException
107 * Initializes a new instance of <code>Socket</code> and connects to the
108 * hostname and port specified as arguments.
110 * @param host The name of the host to connect to
111 * @param port The port number to connect to
113 * @exception UnknownHostException If the hostname cannot be resolved to a
115 * @exception IOException If an error occurs
117 public Socket (String host
, int port
)
118 throws UnknownHostException
, IOException
120 this(InetAddress
.getByName(host
), port
, null, 0, true);
124 * Initializes a new instance of <code>Socket</code> and connects to the
125 * address and port number specified as arguments.
127 * @param address The address to connect to
128 * @param port The port number to connect to
130 * @exception IOException If an error occurs
132 public Socket (InetAddress address
, int port
)
135 this(address
, port
, null, 0, true);
139 * Initializes a new instance of <code>Socket</code> that connects to the
140 * named host on the specified port and binds to the specified local address
143 * @param host The name of the remote host to connect to.
144 * @param port The remote port to connect to.
145 * @param loadAddr The local address to bind to.
146 * @param localPort The local port to bind to.
148 * @exception SecurityException If the <code>SecurityManager</code>
149 * exists and does not allow a connection to the specified host/port or
150 * binding to the specified local host/port.
151 * @exception IOException If a connection error occurs.
153 public Socket (String host
, int port
,
154 InetAddress localAddr
, int localPort
) throws IOException
156 this(InetAddress
.getByName(host
), port
, localAddr
, localPort
, true);
160 * Initializes a new instance of <code>Socket</code> and connects to the
161 * address and port number specified as arguments, plus binds to the
162 * specified local address and port.
164 * @param address The remote address to connect to
165 * @param port The remote port to connect to
166 * @param localAddr The local address to connect to
167 * @param localPort The local port to connect to
169 * @exception IOException If an error occurs
171 public Socket (InetAddress address
, int port
,
172 InetAddress localAddr
, int localPort
) throws IOException
174 this(address
, port
, localAddr
, localPort
, true);
178 * Initializes a new instance of <code>Socket</code> and connects to the
179 * hostname and port specified as arguments. If the stream argument is set
180 * to <code>true</code>, then a stream socket is created. If it is
181 * <code>false</code>, a datagram socket is created.
183 * @param host The name of the host to connect to
184 * @param port The port to connect to
185 * @param stream <code>true</code> for a stream socket, <code>false</code>
186 * for a datagram socket
188 * @exception IOException If an error occurs
190 * @deprecated Use the <code>DatagramSocket</code> class to create
191 * datagram oriented sockets.
193 public Socket (String host
, int port
, boolean stream
) throws IOException
195 this(InetAddress
.getByName(host
), port
, null, 0, stream
);
199 * Initializes a new instance of <code>Socket</code> and connects to the
200 * address and port number specified as arguments. If the stream param is
201 * <code>true</code>, a stream socket will be created, otherwise a datagram
204 * @param host The address to connect to
205 * @param port The port number to connect to
206 * @param stream <code>true</code> to create a stream socket,
207 * <code>false</code> to create a datagram socket.
209 * @exception IOException If an error occurs
211 * @deprecated Use the <code>DatagramSocket</code> class to create
212 * datagram oriented sockets.
214 public Socket (InetAddress host
, int port
, boolean stream
) throws IOException
216 this(host
, port
, null, 0, stream
);
220 * This constructor is where the real work takes place. Connect to the
221 * specified address and port. Use default local values if not specified,
222 * otherwise use the local host and port passed in. Create as stream or
223 * datagram based on "stream" argument.
226 * @param raddr The remote address to connect to
227 * @param rport The remote port to connect to
228 * @param laddr The local address to connect to
229 * @param lport The local port to connect to
230 * @param stream true for a stream socket, false for a datagram socket
232 * @exception IOException If an error occurs
234 private Socket(InetAddress raddr
, int rport
, InetAddress laddr
, int lport
,
235 boolean stream
) throws IOException
239 throw new IOException("Cannot initialize Socket implementation");
241 SecurityManager sm
= System
.getSecurityManager();
243 sm
.checkConnect(raddr
.getHostName(), rport
);
247 // FIXME: JCL p. 1586 says if localPort is unspecified, bind to any port,
248 // i.e. '0' and if localAddr is unspecified, use getLocalAddress() as
249 // that default. JDK 1.2 doc infers not to do a bind.
251 impl
.bind(laddr
, lport
);
254 impl
.connect(raddr
, rport
);
258 * Returns the address of the remote end of the socket. If this socket
259 * is not connected, then <code>null</code> is returned.
261 * @return The remote address this socket is connected to
263 public InetAddress
getInetAddress ()
266 return impl
.getInetAddress();
272 * Returns the local address to which this socket is bound. If this socket
273 * is not connected, then <code>null</code> is returned.
275 * @return The local address
277 public InetAddress
getLocalAddress ()
282 InetAddress addr
= null;
285 addr
= (InetAddress
)impl
.getOption(SocketOptions
.SO_BINDADDR
);
287 catch(SocketException e
)
289 // (hopefully) shouldn't happen
290 // throw new java.lang.InternalError
291 // ("Error in PlainSocketImpl.getOption");
295 // FIXME: According to libgcj, checkConnect() is supposed to be called
296 // before performing this operation. Problems: 1) We don't have the
297 // addr until after we do it, so we do a post check. 2). The docs I
298 // see don't require this in the Socket case, only DatagramSocket, but
299 // we'll assume they mean both.
300 SecurityManager sm
= System
.getSecurityManager();
302 sm
.checkConnect(addr
.getHostName(), getLocalPort());
308 * Returns the port number of the remote end of the socket connection. If
309 * this socket is not connected, then -1 is returned.
311 * @return The remote port this socket is connected to
313 public int getPort ()
316 return impl
.getPort();
322 * Returns the local port number to which this socket is bound. If this
323 * socket is not connected, then -1 is returned.
325 * @return The local port
327 public int getLocalPort ()
330 return impl
.getLocalPort();
336 * Returns an InputStream for reading from this socket.
338 * @return The InputStream object
340 * @exception IOException If an error occurs or Socket is not connected
342 public InputStream
getInputStream () throws IOException
345 return(impl
.getInputStream());
347 throw new IOException("Not connected");
351 * Returns an OutputStream for writing to this socket.
353 * @return The OutputStream object
355 * @exception IOException If an error occurs or Socket is not connected
357 public OutputStream
getOutputStream () throws IOException
360 return impl
.getOutputStream();
362 throw new IOException("Not connected");
366 * Sets the TCP_NODELAY option on the socket.
368 * @param on true to enable, false to disable
370 * @exception SocketException If an error occurs or Socket is not connected
372 public void setTcpNoDelay (boolean on
) throws SocketException
375 throw new SocketException("Not connected");
377 impl
.setOption(SocketOptions
.TCP_NODELAY
, new Boolean(on
));
381 * Tests whether or not the TCP_NODELAY option is set on the socket.
382 * Returns true if enabled, false if disabled. When on it disables the
383 * Nagle algorithm which means that packets are always send immediatly and
384 * never merged together to reduce network trafic.
386 * @return Whether or not TCP_NODELAY is set
388 * @exception SocketException If an error occurs or Socket not connected
390 public boolean getTcpNoDelay() throws SocketException
393 throw new SocketException("Not connected");
395 Object on
= impl
.getOption(SocketOptions
.TCP_NODELAY
);
397 if (on
instanceof Boolean
)
398 return(((Boolean
)on
).booleanValue());
400 throw new SocketException("Internal Error");
404 * Sets the value of the SO_LINGER option on the socket. If the
405 * SO_LINGER option is set on a socket and there is still data waiting to
406 * be sent when the socket is closed, then the close operation will block
407 * until either that data is delivered or until the timeout period
408 * expires. The linger interval is specified in hundreths of a second
409 * (platform specific?)
411 * @param on true to enable SO_LINGER, false to disable
412 * @param linger The SO_LINGER timeout in hundreths of a second or -1 if
415 * @exception SocketException If an error occurs or Socket not connected
417 public void setSoLinger(boolean on
, int linger
) throws SocketException
420 throw new SocketException("No socket created");
425 throw new IllegalArgumentException("SO_LINGER must be >= 0");
430 impl
.setOption(SocketOptions
.SO_LINGER
, new Integer(linger
));
434 impl
.setOption(SocketOptions
.SO_LINGER
, new Boolean(false));
439 * Returns the value of the SO_LINGER option on the socket. If the
440 * SO_LINGER option is set on a socket and there is still data waiting to
441 * be sent when the socket is closed, then the close operation will block
442 * until either that data is delivered or until the timeout period
443 * expires. This method either returns the timeouts (in hundredths of
444 * of a second (platform specific?)) if SO_LINGER is set, or -1 if
445 * SO_LINGER is not set.
447 * @return The SO_LINGER timeout in hundreths of a second or -1
448 * if SO_LINGER not set
450 * @exception SocketException If an error occurs or Socket is not connected
452 public int getSoLinger() throws SocketException
455 throw new SocketException("Not connected");
457 Object linger
= impl
.getOption(SocketOptions
.SO_LINGER
);
458 if (linger
instanceof Integer
)
459 return(((Integer
)linger
).intValue());
465 * Sets the value of the SO_TIMEOUT option on the socket. If this value
466 * is set, and an read/write is performed that does not complete within
467 * the timeout period, a short count is returned (or an EWOULDBLOCK signal
468 * would be sent in Unix if no data had been read). A value of 0 for
469 * this option implies that there is no timeout (ie, operations will
470 * block forever). On systems that have separate read and write timeout
471 * values, this method returns the read timeout. This
472 * value is in thousandths of a second (****????*****)
474 * @param timeout The length of the timeout in thousandth's of a second or
477 * @exception SocketException If an error occurs or Socket not connected
479 public synchronized void setSoTimeout (int timeout
) throws SocketException
482 throw new SocketException("Not connected");
485 throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0");
487 impl
.setOption(SocketOptions
.SO_TIMEOUT
, new Integer(timeout
));
491 * Returns the value of the SO_TIMEOUT option on the socket. If this value
492 * is set, and an read/write is performed that does not complete within
493 * the timeout period, a short count is returned (or an EWOULDBLOCK signal
494 * would be sent in Unix if no data had been read). A value of 0 for
495 * this option implies that there is no timeout (ie, operations will
496 * block forever). On systems that have separate read and write timeout
497 * values, this method returns the read timeout. This
498 * value is in thousandths of a second (implementation specific?).
500 * @return The length of the timeout in thousandth's of a second or 0
503 * @exception SocketException If an error occurs or Socket not connected
505 public synchronized int getSoTimeout () throws SocketException
508 throw new SocketException("Not connected");
510 Object timeout
= impl
.getOption(SocketOptions
.SO_TIMEOUT
);
511 if (timeout
instanceof Integer
)
512 return(((Integer
)timeout
).intValue());
518 * This method sets the value for the system level socket option
519 * SO_SNDBUF to the specified value. Note that valid values for this
520 * option are specific to a given operating system.
522 * @param size The new send buffer size.
524 * @exception SocketException If an error occurs or Socket not connected
528 public void setSendBufferSize (int size
) throws SocketException
531 throw new SocketException("Not connected");
534 throw new IllegalArgumentException("SO_SNDBUF value must be > 0");
536 impl
.setOption(SocketOptions
.SO_SNDBUF
, new Integer(size
));
540 * This method returns the value of the system level socket option
541 * SO_SNDBUF, which is used by the operating system to tune buffer
542 * sizes for data transfers.
544 * @return The send buffer size.
546 * @exception SocketException If an error occurs or socket not connected
550 public int getSendBufferSize () throws SocketException
553 throw new SocketException("Not connected");
555 Object buf
= impl
.getOption(SocketOptions
.SO_SNDBUF
);
557 if (buf
instanceof Integer
)
558 return(((Integer
)buf
).intValue());
560 throw new SocketException("Internal Error: Unexpected type");
564 * This method sets the value for the system level socket option
565 * SO_RCVBUF to the specified value. Note that valid values for this
566 * option are specific to a given operating system.
568 * @param size The new receive buffer size.
570 * @exception SocketException If an error occurs or Socket is not connected
574 public void setReceiveBufferSize (int size
) throws SocketException
577 throw new SocketException("Not connected");
580 throw new IllegalArgumentException("SO_RCVBUF value must be > 0");
582 impl
.setOption(SocketOptions
.SO_RCVBUF
, new Integer(size
));
586 * This method returns the value of the system level socket option
587 * SO_RCVBUF, which is used by the operating system to tune buffer
588 * sizes for data transfers.
590 * @return The receive buffer size.
592 * @exception SocketException If an error occurs or Socket is not connected
596 public int getReceiveBufferSize () throws SocketException
599 throw new SocketException("Not connected");
601 Object buf
= impl
.getOption(SocketOptions
.SO_RCVBUF
);
603 if (buf
instanceof Integer
)
604 return(((Integer
)buf
).intValue());
606 throw new SocketException("Internal Error: Unexpected type");
612 * @exception IOException If an error occurs
614 public synchronized void close () throws IOException
621 * Converts this <code>Socket</code> to a <code>String</code>.
623 * @return The <code>String</code> representation of this <code>Socket</code>
625 public String
toString ()
627 return("Socket " + impl
);
633 * Sets the <code>SocketImplFactory</code>. This may be done only once per
634 * virtual machine. Subsequent attempts will generate a
635 * <code>SocketException</code>. Note that a <code>SecurityManager</code>
636 * check is made prior to setting the factory. If
637 * insufficient privileges exist to set the factory, then an
638 * <code>IOException</code> will be thrown.
640 * @exception SecurityException If the <code>SecurityManager</code> does
641 * not allow this operation.
642 * @exception SocketException If the SocketImplFactory is already defined
643 * @exception IOException If any other error occurs
645 public static synchronized void setSocketImplFactory (SocketImplFactory fac
)
648 // See if already set
650 throw new SocketException("SocketImplFactory already defined");
653 SecurityManager sm
= System
.getSecurityManager();
655 sm
.checkSetFactory();