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