home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / net / Socket.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  20.7 KB  |  596 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)Socket.java    1.42 98/09/24
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.net;
  16.  
  17. import java.io.InputStream;
  18. import java.io.OutputStream;
  19. import java.io.IOException;
  20. import java.io.InterruptedIOException;
  21. import java.security.AccessController;
  22. import java.security.PrivilegedExceptionAction;
  23.  
  24. /**
  25.  * This class implements client sockets (also called just
  26.  * "sockets"). A socket is an endpoint for communication
  27.  * between two machines.
  28.  * <p>
  29.  * The actual work of the socket is performed by an instance of the
  30.  * <code>SocketImpl</code> class. An application, by changing
  31.  * the socket factory that creates the socket implementation,
  32.  * can configure itself to create sockets appropriate to the local
  33.  * firewall.
  34.  *
  35.  * @author  unascribed
  36.  * @version 1.42, 09/24/98
  37.  * @see     java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory)
  38.  * @see     java.net.SocketImpl
  39.  * @since   JDK1.0
  40.  */
  41. public
  42. class Socket {
  43.     /**
  44.      * The implementation of this Socket.
  45.      */
  46.     SocketImpl impl;
  47.  
  48.     /**
  49.      * Creates an unconnected socket, with the
  50.      * system-default type of SocketImpl.
  51.      *
  52.      * @since   JDK1.1
  53.      */
  54.     protected Socket() {
  55.     impl = (factory != null) ? factory.createSocketImpl() :
  56.         new PlainSocketImpl();
  57.     }
  58.  
  59.     /**
  60.      * Creates an unconnected Socket with a user-specified
  61.      * SocketImpl.
  62.      * <P>
  63.      * The <i>impl</i> parameter is an instance of a <B>SocketImpl</B>
  64.      * the subclass wishes to use on the Socket.
  65.      *
  66.      * @since   JDK1.1
  67.      */
  68.     protected Socket(SocketImpl impl) throws SocketException {
  69.     this.impl = impl;
  70.     }
  71.  
  72.     /**
  73.      * Creates a stream socket and connects it to the specified port
  74.      * number on the named host.
  75.      * <p>
  76.      * If the application has specified a server socket factory, that
  77.      * factory's <code>createSocketImpl</code> method is called to create
  78.      * the actual socket implementation. Otherwise a "plain" socket is created.
  79.      * <p>
  80.      * If there is a security manager, its
  81.      * <code>checkConnect</code> method is called
  82.      * with the host address and <code>port</code> 
  83.      * as its arguments. This could result in a SecurityException.
  84.      *
  85.      * @param      host   the host name.
  86.      * @param      port   the port number.
  87.      * @exception  IOException  if an I/O error occurs when creating the socket.
  88.      * @exception  SecurityException  if a security manager exists and its  
  89.      *             <code>checkConnect</code> method doesn't allow the operation.
  90.      * @see        java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory)
  91.      * @see        java.net.SocketImpl
  92.      * @see        java.net.SocketImplFactory#createSocketImpl()
  93.      * @see        SecurityManager#checkConnect
  94.      */
  95.     public Socket(String host, int port)
  96.     throws UnknownHostException, IOException
  97.     {
  98.     this(InetAddress.getByName(host), port, null, 0, true);
  99.     }
  100.  
  101.     /**
  102.      * Creates a stream socket and connects it to the specified port
  103.      * number at the specified IP address.
  104.      * <p>
  105.      * If the application has specified a socket factory, that factory's
  106.      * <code>createSocketImpl</code> method is called to create the
  107.      * actual socket implementation. Otherwise a "plain" socket is created.
  108.      * <p>
  109.      * If there is a security manager, its
  110.      * <code>checkConnect</code> method is called
  111.      * with the host address and <code>port</code> 
  112.      * as its arguments. This could result in a SecurityException.
  113.      * 
  114.      * @param      address   the IP address.
  115.      * @param      port      the port number.
  116.      * @exception  IOException  if an I/O error occurs when creating the socket.
  117.      * @exception  SecurityException  if a security manager exists and its  
  118.      *             <code>checkConnect</code> method doesn't allow the operation.
  119.      * @see        java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory)
  120.      * @see        java.net.SocketImpl
  121.      * @see        java.net.SocketImplFactory#createSocketImpl()
  122.      * @see        SecurityManager#checkConnect
  123.      */
  124.     public Socket(InetAddress address, int port) throws IOException {
  125.     this(address, port, null, 0, true);
  126.     }
  127.  
  128.     /**
  129.      * Creates a socket and connects it to the specified remote host on
  130.      * the specified remote port. The Socket will also bind() to the local
  131.      * address and port supplied.
  132.      * <p>
  133.      * If there is a security manager, its
  134.      * <code>checkConnect</code> method is called
  135.      * with the host address and <code>port</code> 
  136.      * as its arguments. This could result in a SecurityException.
  137.      * 
  138.      * @param host the name of the remote host
  139.      * @param port the remote port
  140.      * @param localAddr the local address the socket is bound to
  141.      * @param localPort the local port the socket is bound to
  142.      * @exception  SecurityException  if a security manager exists and its  
  143.      *             <code>checkConnect</code> method doesn't allow the operation.
  144.      * @see        SecurityManager#checkConnect
  145.      * @since   JDK1.1
  146.      */
  147.     public Socket(String host, int port, InetAddress localAddr,
  148.           int localPort) throws IOException {
  149.     this(InetAddress.getByName(host), port, localAddr, localPort, true);
  150.     }
  151.  
  152.     /**
  153.      * Creates a socket and connects it to the specified remote address on
  154.      * the specified remote port. The Socket will also bind() to the local
  155.      * address and port supplied.
  156.      * <p>
  157.      * If there is a security manager, its
  158.      * <code>checkConnect</code> method is called
  159.      * with the host address and <code>port</code> 
  160.      * as its arguments. This could result in a SecurityException.
  161.      * 
  162.      * @param address the remote address
  163.      * @param port the remote port
  164.      * @param localAddr the local address the socket is bound to
  165.      * @param localPort the local port the socket is bound to
  166.      * @exception  SecurityException  if a security manager exists and its  
  167.      *             <code>checkConnect</code> method doesn't allow the operation.
  168.      * @see        SecurityManager#checkConnect
  169.      * @since   JDK1.1
  170.      */
  171.     public Socket(InetAddress address, int port, InetAddress localAddr,
  172.           int localPort) throws IOException {
  173.               this(address, port, localAddr, localPort, true);
  174.     }
  175.  
  176.     /**
  177.      * Creates a stream socket and connects it to the specified port
  178.      * number on the named host.
  179.      * <p>
  180.      * If the stream argument is <code>true</code>, this creates a
  181.      * stream socket. If the stream argument is <code>false</code>, it
  182.      * creates a datagram socket.
  183.      * <p>
  184.      * If the application has specified a server socket factory, that
  185.      * factory's <code>createSocketImpl</code> method is called to create
  186.      * the actual socket implementation. Otherwise a "plain" socket is created.
  187.      * <p>
  188.      * If there is a security manager, its
  189.      * <code>checkConnect</code> method is called
  190.      * with the host address and <code>port</code> 
  191.      * as its arguments. This could result in a SecurityException.
  192.      *
  193.      * @param      host     the host name.
  194.      * @param      port     the port number.
  195.      * @param      stream   a <code>boolean</code> indicating whether this is
  196.      *                      a stream socket or a datagram socket.
  197.      * @exception  IOException  if an I/O error occurs when creating the socket.
  198.      * @exception  SecurityException  if a security manager exists and its  
  199.      *             <code>checkConnect</code> method doesn't allow the operation.
  200.      * @see        java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory)
  201.      * @see        java.net.SocketImpl
  202.      * @see        java.net.SocketImplFactory#createSocketImpl()
  203.      * @see        SecurityManager#checkConnect
  204.      * @deprecated Use DatagramSocket instead for UDP transport.
  205.      */
  206.     public Socket(String host, int port, boolean stream) throws IOException {
  207.     this(InetAddress.getByName(host), port, null, 0, stream);
  208.     }
  209.  
  210.     /**
  211.      * Creates a socket and connects it to the specified port number at
  212.      * the specified IP address.
  213.      * <p>
  214.      * If the stream argument is <code>true</code>, this creates a
  215.      * stream socket. If the stream argument is <code>false</code>, it
  216.      * creates a datagram socket.
  217.      * <p>
  218.      * If the application has specified a server socket factory, that
  219.      * factory's <code>createSocketImpl</code> method is called to create
  220.      * the actual socket implementation. Otherwise a "plain" socket is created.
  221.      * 
  222.      * <p>If there is a security manager, its
  223.      * <code>checkConnect</code> method is called
  224.      * with <code>host.getHostAddress()</code> and <code>port</code> 
  225.      * as its arguments. This could result in a SecurityException.
  226.      *
  227.      * @param      host     the IP address.
  228.      * @param      port      the port number.
  229.      * @param      stream    if <code>true</code>, create a stream socket;
  230.      *                       otherwise, create a datagram socket.
  231.      * @exception  IOException  if an I/O error occurs when creating the socket.
  232.      * @exception  SecurityException  if a security manager exists and its  
  233.      *             <code>checkConnect</code> method doesn't allow the operation.
  234.      * @see        java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory)
  235.      * @see        java.net.SocketImpl
  236.      * @see        java.net.SocketImplFactory#createSocketImpl()
  237.      * @see        SecurityManager#checkConnect
  238.      * @deprecated Use DatagramSocket instead for UDP transport.
  239.      */
  240.     public Socket(InetAddress host, int port, boolean stream) throws IOException {
  241.     this(host, port, null, 0, stream);
  242.     }
  243.  
  244.     private Socket(InetAddress address, int port, InetAddress localAddr,
  245.           int localPort, boolean stream) throws IOException {
  246.     this();
  247.  
  248.     if (port < 0 || port > 0xFFFF) {
  249.         throw new IllegalArgumentException("port out range:"+port);
  250.     }
  251.  
  252.     if (localPort < 0 || localPort > 0xFFFF) {
  253.         throw new IllegalArgumentException("port out range:"+localPort);
  254.     }
  255.  
  256.     SecurityManager security = System.getSecurityManager();
  257.     if (security != null) {
  258.         security.checkConnect(address.getHostAddress(), port);
  259.     }
  260.  
  261.     try {
  262.         impl.create(stream);
  263.         if (localAddr != null || localPort > 0) {
  264.         if (localAddr == null) {
  265.             localAddr = InetAddress.anyLocalAddress;
  266.         }
  267.         impl.bind(localAddr, localPort);
  268.         }
  269.         impl.connect(address, port);
  270.     } catch (SocketException e) {
  271.         impl.close();
  272.         throw e;
  273.     }
  274.     }
  275.  
  276.     /**
  277.      * Returns the address to which the socket is connected.
  278.      *
  279.      * @return  the remote IP address to which this socket is connected.
  280.      */
  281.     public InetAddress getInetAddress() {
  282.     return impl.getInetAddress();
  283.     }
  284.  
  285.     /**
  286.      * Gets the local address to which the socket is bound.
  287.      *
  288.      * @since   JDK1.1
  289.      */
  290.     public InetAddress getLocalAddress() {
  291.     InetAddress in = null;
  292.     try {
  293.         in = (InetAddress) impl.getOption(SocketOptions.SO_BINDADDR);
  294.     } catch (Exception e) {
  295.         in = InetAddress.anyLocalAddress; // "0.0.0.0"
  296.     }
  297.     return in;
  298.     }
  299.  
  300.     /**
  301.      * Returns the remote port to which this socket is connected.
  302.      *
  303.      * @return  the remote port number to which this socket is connected.
  304.      */
  305.     public int getPort() {
  306.     return impl.getPort();
  307.     }
  308.  
  309.     /**
  310.      * Returns the local port to which this socket is bound.
  311.      *
  312.      * @return  the local port number to which this socket is connected.
  313.      */
  314.     public int getLocalPort() {
  315.     return impl.getLocalPort();
  316.     }
  317.  
  318.     /**
  319.      * Returns an input stream for this socket.
  320.      *
  321.      * @return     an input stream for reading bytes from this socket.
  322.      * @exception  IOException  if an I/O error occurs when creating the
  323.      *               input stream.
  324.      */
  325.     public InputStream getInputStream() throws IOException {
  326.     try {
  327.         return (InputStream)
  328.         AccessController.doPrivileged(new PrivilegedExceptionAction() {
  329.             public Object run() throws IOException {
  330.             return impl.getInputStream();
  331.             }
  332.         });
  333.     } catch (java.security.PrivilegedActionException e) {
  334.         throw (IOException) e.getException();
  335.     }
  336.     }
  337.  
  338.     /**
  339.      * Returns an output stream for this socket.
  340.      *
  341.      * @return     an output stream for writing bytes to this socket.
  342.      * @exception  IOException  if an I/O error occurs when creating the
  343.      *               output stream.
  344.      */
  345.     public OutputStream getOutputStream() throws IOException {
  346.     try {
  347.         return (OutputStream)
  348.         AccessController.doPrivileged(new PrivilegedExceptionAction() {
  349.             public Object run() throws IOException {
  350.             return impl.getOutputStream();
  351.             }
  352.         });
  353.     } catch (java.security.PrivilegedActionException e) {
  354.         throw (IOException) e.getException();
  355.     }
  356.     }
  357.  
  358.     /**
  359.      * Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm).
  360.      *
  361.      * @since   JDK1.1
  362.      */
  363.     public void setTcpNoDelay(boolean on) throws SocketException {
  364.     impl.setOption(SocketOptions.TCP_NODELAY, new Boolean(on));
  365.     }
  366.  
  367.     /**
  368.      * Tests if TCP_NODELAY is enabled.
  369.      *
  370.      * @since   JDK1.1
  371.      */
  372.     public boolean getTcpNoDelay() throws SocketException {
  373.     return ((Boolean) impl.getOption(SocketOptions.TCP_NODELAY)).booleanValue();
  374.     }
  375.  
  376.     /**
  377.      * Enable/disable SO_LINGER with the specified linger time in seconds. 
  378.      * If the specified timeout value exceeds 65,535 it will be reduced to
  379.      * 65,535.
  380.      * 
  381.      * @param on     whether or not to linger on.
  382.      * @param linger how to linger for, if on is true.
  383.      * @exception IllegalArgumentException if the linger value is negative.
  384.      * @since JDK1.1 
  385.      */
  386.     public void setSoLinger(boolean on, int linger) throws SocketException {
  387.     if (!on) {
  388.         impl.setOption(SocketOptions.SO_LINGER, new Boolean(on));
  389.     } else {
  390.         if (linger < 0) {
  391.         throw new IllegalArgumentException("invalid value for SO_LINGER");
  392.         }
  393.             if (linger > 65535)
  394.                 linger = 65535;
  395.         impl.setOption(SocketOptions.SO_LINGER, new Integer(linger));
  396.     }
  397.     }
  398.  
  399.     /**
  400.      * Returns setting for SO_LINGER. -1 returns implies that the
  401.      * option is disabled.
  402.      *
  403.      * @since   JDK1.1
  404.      */
  405.     public int getSoLinger() throws SocketException {
  406.     Object o = impl.getOption(SocketOptions.SO_LINGER);
  407.     if (o instanceof Integer) {
  408.         return ((Integer) o).intValue();
  409.     } else {
  410.         return -1;
  411.     }
  412.     }
  413.  
  414.     /**
  415.      *  Enable/disable SO_TIMEOUT with the specified timeout, in
  416.      *  milliseconds.  With this option set to a non-zero timeout,
  417.      *  a read() call on the InputStream associated with this Socket
  418.      *  will block for only this amount of time.  If the timeout expires,
  419.      *  a <B>java.io.InterruptedIOException</B> is raised, though the
  420.      *  Socket is still valid. The option <B>must</B> be enabled
  421.      *  prior to entering the blocking operation to have effect. The
  422.      *  timeout must be > 0.
  423.      *  A timeout of zero is interpreted as an infinite timeout.
  424.      *
  425.      * @since   JDK 1.1
  426.      */
  427.     public synchronized void setSoTimeout(int timeout) throws SocketException {
  428.     impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
  429.     }
  430.  
  431.     /**
  432.      * Returns setting for SO_TIMEOUT.  0 returns implies that the
  433.      * option is disabled (i.e., timeout of infinity).
  434.      *
  435.      * @since   JDK1.1
  436.      */
  437.     public synchronized int getSoTimeout() throws SocketException {
  438.     Object o = impl.getOption(SocketOptions.SO_TIMEOUT);
  439.     /* extra type safety */
  440.     if (o instanceof Integer) {
  441.         return ((Integer) o).intValue();
  442.     } else {
  443.         return 0;
  444.     }
  445.     }
  446.  
  447.     /**
  448.      * Sets the SO_SNDBUF option to the specified value for this
  449.      * DatagramSocket. The SO_SNDBUF option is used by the platform's
  450.      * networking code as a hint for the size to use to allocate set
  451.      * the underlying network I/O buffers.
  452.      *
  453.      * <p>Increasing buffer size can increase the performance of
  454.      * network I/O for high-volume connection, while decreasing it can
  455.      * help reduce the backlog of incoming data. For UDP, this sets
  456.      * the maximum size of a packet that may be sent on this socket.
  457.      *
  458.      * <p>Because SO_SNDBUF is a hint, applications that want to
  459.      * verify what size the buffers were set to should call
  460.      * <href="#getSendBufferSize>getSendBufferSize</a>.
  461.      *
  462.      * @param size the size to which to set the send buffer
  463.      * size. This value must be greater than 0.
  464.      *
  465.      * @exception IllegalArgumentException if the value is 0 or is
  466.      * negative.
  467.      */
  468.     public synchronized void setSendBufferSize(int size)
  469.     throws SocketException{
  470.     if (!(size > 0)) {
  471.         throw new IllegalArgumentException("negative send size");
  472.     }
  473.     impl.setOption(SocketOptions.SO_SNDBUF, new Integer(size));
  474.     }
  475.  
  476.     /**
  477.      * Get value of the SO_SNDBUF option for this socket, that is the
  478.      * buffer size used by the platform for output on the this Socket.
  479.      *
  480.      * @see #setSendBufferSize
  481.      */
  482.     public synchronized int getSendBufferSize() throws SocketException {
  483.     int result = 0;
  484.     Object o = impl.getOption(SocketOptions.SO_SNDBUF);
  485.     if (o instanceof Integer) {
  486.         result = ((Integer)o).intValue();
  487.     }
  488.     return result;
  489.     }
  490.  
  491.     /**
  492.      * Sets the SO_RCVBUF option to the specified value for this
  493.      * DatagramSocket. The SO_RCVBUF option is used by the platform's
  494.      * networking code as a hint for the size to use to allocate set
  495.      * the underlying network I/O buffers.
  496.      *
  497.      * <p>Increasing buffer size can increase the performance of
  498.      * network I/O for high-volume connection, while decreasing it can
  499.      * help reduce the backlog of incoming data. For UDP, this sets
  500.      * the maximum size of a packet that may be sent on this socket.
  501.      *
  502.      * <p>Because SO_RCVBUF is a hint, applications that want to
  503.      * verify what size the buffers were set to should call
  504.      * <href="#getReceiveBufferSize>getReceiveBufferSize</a>.
  505.      *
  506.      * @param size the size to which to set the receive buffer
  507.      * size. This value must be greater than 0.
  508.      *
  509.      * @exception IllegalArgumentException if the value is 0 or is
  510.      * negative.
  511.      */
  512.     public synchronized void setReceiveBufferSize(int size)
  513.     throws SocketException{
  514.     if (size < 0) {
  515.         throw new IllegalArgumentException("invalid receive size");
  516.     }
  517.     impl.setOption(SocketOptions.SO_RCVBUF, new Integer(size));
  518.     }
  519.  
  520.     /**
  521.      * Get value of the SO_RCVBUF option for this socket, that is the
  522.      * buffer size used by the platform for input on the this Socket.
  523.      *
  524.      * @see #setReceiveBufferSize
  525.      */
  526.     public synchronized int getReceiveBufferSize()
  527.     throws SocketException{
  528.     int result = 0;
  529.     Object o = impl.getOption(SocketOptions.SO_RCVBUF);
  530.     if (o instanceof Integer) {
  531.         result = ((Integer)o).intValue();
  532.     }
  533.     return result;
  534.     }
  535.  
  536.     /**
  537.      * Closes this socket.
  538.      *
  539.      * @exception  IOException  if an I/O error occurs when closing this socket.
  540.      */
  541.     public synchronized void close() throws IOException {
  542.     impl.close();
  543.     }
  544.  
  545.     /**
  546.      * Converts this socket to a <code>String</code>.
  547.      *
  548.      * @return  a string representation of this socket.
  549.      */
  550.     public String toString() {
  551.     return "Socket[addr=" + impl.getInetAddress() +
  552.         ",port=" + impl.getPort() +
  553.         ",localport=" + impl.getLocalPort() + "]";
  554.     }
  555.  
  556.     /**
  557.      * The factory for all client sockets.
  558.      */
  559.     private static SocketImplFactory factory;
  560.  
  561.     /**
  562.      * Sets the client socket implementation factory for the
  563.      * application. The factory can be specified only once.
  564.      * <p>
  565.      * When an application creates a new client socket, the socket
  566.      * implementation factory's <code>createSocketImpl</code> method is
  567.      * called to create the actual socket implementation.
  568.      * 
  569.      * <p>If there is a security manager, this method first calls
  570.      * the security manager's <code>checkSetFactory</code> method 
  571.      * to ensure the operation is allowed. 
  572.      * This could result in a SecurityException.
  573.      *
  574.      * @param      fac   the desired factory.
  575.      * @exception  IOException  if an I/O error occurs when setting the
  576.      *               socket factory.
  577.      * @exception  SocketException  if the factory is already defined.
  578.      * @exception  SecurityException  if a security manager exists and its  
  579.      *             <code>checkSetFactory</code> method doesn't allow the operation.
  580.      * @see        java.net.SocketImplFactory#createSocketImpl()
  581.       * @see       SecurityManager#checkSetFactory
  582.     */
  583.     public static synchronized void setSocketImplFactory(SocketImplFactory fac)
  584.     throws IOException
  585.     {
  586.     if (factory != null) {
  587.         throw new SocketException("factory already defined");
  588.     }
  589.     SecurityManager security = System.getSecurityManager();
  590.     if (security != null) {
  591.         security.checkSetFactory();
  592.     }
  593.     factory = fac;
  594.     }
  595. }
  596.