Home > Articles > Programming > Java

This chapter is from the book

6.4 Socket Class

The Socket class represents client sockets, and is a communication channel between two TCP communications ports belonging to one or two machines. A socket may connect to a port on the local system, avoiding the need for a second machine, but most network software will usually involve two machines. TCP sockets can't communicate with more than two machines, however. If this functionality is required, a client application should establish multiple socket connections, one for each machine.

Constructors

There are several constructors for the java.net.Socket class. Two constructors, which allowed a boolean parameter to specify whether UDP or TCP sockets were to be used, have been deprecated. These constructors should not be used and are not listed here—if UDP functionality is required, use a DatagramSocket (covered in Chapter 5).

The easiest way to create a socket is to specify the hostname of the machine and the port of the service. For example, to connect to a Web server on port 80, the following code might be used:

try
{
      // Connect to the specified host and port
      Socket mySocket = new Socket ( "www.awl.com", 80);

      // ......
}
catch (Exception e)
{
      System.err.println ("Err – " + e);
}

However, a wide range of constructors is available, for different situations. Unless otherwise specified, all constructors are public.

  • protected Socket ()—creates an unconnected socket using the default implementation provided by the current socket factory. Developers should not normally use this method, as it does not allow a hostname or port to be specified.

  • Socket (InetAddress address, int port) throws java.io.IOException,

  • java.lang.SecurityException—creates a socket connected to the specified IP address and port. If a connection cannot be established, or if connecting to that host violates a security restriction (such as when an applet tries to connect to a machine other than the machine from which it was loaded), an exception is thrown.

  • Socket (InetAddress address, int port, InetAddress localAddress, int localPort) throws java.io.IOException, java.lang.SecurityException—creates a socket connected to the specified address and port, and is bound to the specified local address and local port. By default, a free port is used, but this method allows you to specify a specific port number, as well as a specific address, in the case of multi-homed hosts (i.e., a machine where the localhost is known by two or more IP addresses).

  • protected Socket (SocketImpl implementation)—creates an unconnected socket using the specified socket implementation. Developers should not normally use this method, as it does not allow a hostname or port to be specified.

  • Socket (String host, int port) throws java.net.UnknownHostException, java.io.IOException, java.lang.SecurityException—creates a socket connected to the specified host and port. This method allows a string to be specified, rather than an InetAddress. If the hostname could not be resolved, a connection could not be established, or a security restriction is violated, an exception is thrown.

  • Socket (String host, int port, InetAddress localAddress, int localPort) throws java.net.UnknownHostException, java.io.IOException, java.lang.SecurityException—creates a socket connected to the specified host and port, and bound to the specified local port and address. This allows a hostname to be specified as a string, and not an InetAddress instance, as well as allowing a specific local address and port to be bound to. These local parameters are useful for multihomed hosts (i.e., a machine where the localhost is known by two or more IP addresses). If the hostname can't be resolved, a connection cannot be established, or a security restriction is violated, an exception is thrown.

6.4.1 Creating a Socket

Under normal circumstances, a socket is connected to a machine and port when it is created. Although there is a blank constructor that does not require a hostname or port, it is protected and can't be called from normal applications. Furthermore, there isn't a connect() method that allows you to specify these details at a later point in time, so under normal circumstances the socket will be connected when created. If the network is fine, the call to a socket constructor will return as soon as a connection is established, but if the remote machine is not responding, the constructor method may block for an indefinite amount of time. This varies from system to system, depending on a variety of factors such as the operating system being used and the default network timeout (some machines on a local intranet, for example, seem to respond faster than some Internet machines, depending on network settings). You can't ever guarantee how long a socket may block for, but this is abnormal behavior and won't happen frequently. Nonetheless, in mission-critical systems it may be appropriate to place such calls in a second thread, to prevent an application from stalling.

NOTE

At a lower level, sockets are produced by a socket factory, which is a special class responsible for creating the appropriate socket implementation. Under normal circumstances, a standard java.net.Socket will be produced, but in special situations, such as special networking environments in which custom sockets are used (for example, to break through a firewall by using a special proxy server), socket factories may actually return a socket subclass. The details of socket factories are best left to experienced developers who are familiar with the intricacies of Java networking and have a definite purpose for creating custom sockets and socket factories. For more information on this topic, consult the Java API documentation for the java.net.SocketFactory and java.net.SocketImplFactory class.

6.4.2 Using a Socket

Sockets can perform a variety of tasks, such as reading information, sending data, closing a connection, and setting socket options. In addition, the following methods are provided to obtain information about a socket, such as address and port locations:

Methods

  • void close() throws java.io.IOException—closes the socket connection. Closing a connect may or may not allow remaining data to be sent, depending on the value of the SO_LINGER socket option. Developers are advised to flush any output streams before closing a socket connection.

  • InetAddress getInetAddress()—returns the address of the remote machine that is connected to the socket.

  • InputStream getInputStream() throws java.io.IOException—returns an input stream, which reads from the application this socket is connected to.

  • OutputStream getOutputStream() throws java.io.IOException—returns an output stream, which writes to the application that this socket is connected to.

  • boolean getKeepAlive() throws java.net.SocketException—returns the state of the SO_KEEPALIVE socket option.

  • InetAddress getLocalAddress()—returns the local address associated with the socket (useful in the case of multihomed machines).

  • int getLocalPort()—returns the port number that the socket is bound to on the local machine.

  • int getPort()—returns the port number of the remote service to which the socket is connected.

  • int getReceiveBufferSize() throws java.net.SocketException—returns the receive buffer size used by the socket, determined by the value of the SO_RCVBUF socket option.

  • int getSendBufferSize() throws java.net.SocketException—returns the send buffer size used by the socket, determined by the value of the SO_SNDBUF socket option.

  • int getSoLinger() throws java.net.SocketException—returns the value of the SO_LINGER socket option, which controls how long unsent data will be queued when a connection is terminated.

  • int getSoTimeout() throws java.net.SocketException—returns the value of the SO_TIMEOUT socket option, which controls how many milliseconds a read operation will block for. If a value of 0 is returned, the timer is disabled and a thread will block indefinitely (until data is available or the stream is terminated).

  • boolean getTcpNoDelay() throws java.net.SocketException—returns "true" if the TCP_NODELAY socket option is set, which controls whether Nagle's algorithm (discussed in Section 6.4.4.5) is enabled.

  • void setKeepAlive(boolean onFlag) throws java.net.SocketException—enables or disables the SO_KEEPALIVE socket option.

  • void setReceiveBufferSize(int size) throws java.net.SocketException—modifies the value of the SO_RCVBUF socket option, which recommends a buffer size for the operating system's network code to use for receiving incoming data. Not every system will support this functionality or allows absolute control over this feature. If you want to buffer incoming data, you're advised to instead use a BufferedInputStream or a BufferedReader.

  • void setSendBufferSize(int size) throws java.net.SocketException—modifies the value of the SO_SNDBUF socket option, which recommends a buffer size for the operating system's network code to use for sending incoming data. Not every system will support this functionality or allows absolute control over this feature. If you want to buffer incoming data, you're advised to instead use a BufferedOutputStream or a BufferedWriter.

  • static void setSocketImplFactory (SocketImplFactory factory) throws java.net.SocketException, java.io.IOException, java. lang.SecurityException —assigns a socket implementation factory for the JVM, which may already exist, or may violate security restrictions, either of which causes an exception to be thrown. Only one factory can be specified, and this factory will be used whenever a socket is created.

  • void setSoLinger(boolean onFlag, int duration) throws java.net. SocketException, java.lang.IllegalArgumentException—enables or disables the SO_LINGER socket option (according to the value of the onFlag boolean parameter), and specifies a duration in seconds. If a negative value is specified, an exception is thrown.

  • void setSoTimeout(int duration) throws java.net.SocketException—modifies the value of the SO_TIMEOUT socket option, which controls how long (in milliseconds) a read operation will block. A value of zero disables timeouts, and blocks indefinitely. If a timeout does occur, a java.io.IOInterruptedException is thrown whenever a read operation occurs on the socket's input stream. This is distinct from the internal TCP timer, which triggers a resend of unacknowledged datagram packets (see Section 6.1.1.1 on error control).

  • void setTcpNoDelay(boolean onFlag) throws java.net.SocketException—enables or disables the TCP_NODELAY socket option, which determines whether Nagle's algorithm is used.

  • void shutdownInput() throws java.io.IOException—closes the input stream associated with this socket and discards any further information that is sent. Further reads to the input stream will encounter the end of the stream marker.

  • void shutdownOutput() throws java.io.IOException—closes the output stream associated with this socket. Any data previously written, but not yet sent, will be flushed, followed by a TCP connection-termination sequence, which notifies the application that no more data will be available (and in the case of a Java application, that the end of the stream has been reached). Further writes to the socket will cause an IOException to be thrown.

6.4.3 Reading from and Writing to TCP Sockets

Creating client software that uses TCP for communication is extremely easy in Java, no matter what operating system is being used. The Java Networking API provides a consistent, platform-neutral interface that allows client applications to connect to remote services. Once a socket is created, it is connected and ready to read/write by using the socket's input and output streams. These streams don't need to be created; they are provided by the Socket. getInputStream() and Socket.getOutputStream() methods. As was shown in Chapter 4 on I/O streams, filtered streams provide easy I/O access.

A filter can easily be connected to a socket stream, to make for simpler programming. The following code snippet demonstrates a simple TCP client that connects a BufferedReader to the socket input stream, and a PrintStream to the socket output stream.

try
{
      // Connect a socket to some host machine and port
      Socket socket = new Socket ( somehost, someport );

      // Connect a buffered reader
      BufferedReader reader = new BufferedReader ( 
          new InputStreamReader ( socket.getInputStream() ) );

      // Connect a print stream
      PrintStream pstream = 
          new PrintStream( socket.getOutputStream() );
}
catch (Exception e)
{
      System.err.println ("Error – " + e);
}

6.4.4 Socket Options

Socket options are settings that modify how sockets work, and they can affect (both positively and negatively) the performance of applications. Support for socket options was introduced in Java 1.1, and some refinements have been made in later versions (such as support for the SO_KEEPALIVE option in Java 2 v 1.3). Generally, socket options should not be changed unless there is a good reason for doing so, as changes may negatively affect application and network performance (for example, enabling Nagle's algorithm may increase performance of telnet type applications but lower the available bandwidth). The one exception to this caveat is the SO_TIMEOUT option—virtually every TCP application should handle timeouts gracefully rather than stalling if the application the socket is connected to fails to transmit data when required.

6.4.4.1 SO_KEEPALIVE Socket Option

The keepalive socket option is controversial; its use is a topic that some developers feel very strongly about. By default, no data is sent between two connected sockets unless an application has data to send. This means that an idle socket may not have data submitted for minutes, hours, or even days in the case of long-lived processes. Suppose, however, that a client crashes, and the end-of-connection sequence is not sent to a TCP server. Valuable resources (CPU time and memory) might be wasted on a client that will never respond. When the keepalive socket option is enabled, the other end of the socket is probed to verify it is still active. However, the application doesn't have any control over how often keepalive probes are sent. To enable keepalive, the Socket.setSoKeepAlive(boolean) method is called with a value of "true" (a value of "false" will disable it). For example, to enable keepalive on a socket, the following code would be used.

// Enable SO_KEEPALIVE
someSocket.setSoKeepAlive(true);

Although keepalive does have some advantages, many developers advocate controlling timeouts and dead sockets at a higher level, in application code. It should also be kept in mind that keepalive doesn't allow you to specify a value for probing socket endpoints. A better solution than keepalive, and one that developers are advised to use, is to instead modify the timeout socket option.

6.4.4.2 SO_RCVBUF Socket Option

The receive buffer socket option controls the buffer used for receiving data. Changes can be made to the size by calling the Socket.setReceiveBufferSize(int) method. For example, to increase the receive buffer size to 4,096 bytes, the following code would be used.

// Modify receive buffer size
someSocket.setReceiveBufferSize(4096);

Note that a request to modify the size of the receive buffer does not guarantee that it will change. For example, some operating systems may not allow this socket option to be modified, and will ignore any changes to the value. The current buffer size can be determined by invoking the Socket. getReceiveBufferSize() method. A better choice for buffering is to use a BufferedInputStream/BufferedReader.

6.4.4.3 SO_SNDBUF Socket Option

The send buffer socket option controls the size of the buffer used for sending data. By calling the Socket.setSendBufferSize(int) method, you can attempt to change the buffer size, but requests to change the size may be rejected by the operating system.

// Set the send buffer size to 4096 bytes
someSocket.setSendBufferSize(4096);

To determine the size of the current send buffer, you can call the Socket.getSendBufferSize() method, which returns an int value.

// Get the default size
int size = someSocket.getSendBufferSize();

Changing buffer size will be more effective with the DatagramSocket class. When buffering writes, the preferable choice is to use a BufferedOutputStream or a BufferedWriter.

6.4.4.4 SO_LINGER Socket Option

When a TCP socket connection is closed, it is possible that data may be queued for delivery and not yet sent (particularly if an IP datagram becomes lost in transit and must be resent). The linger socket option controls the amount of time during which unsent data may be sent, after which it is discarded completely. It is possible to enable/disable the linger option entirely, or to modify the duration of a linger, by using the Socket.setSoLinger(boolean onFlag, int duration) method:

// Enable linger, for fifty seconds
someSocket.setSoLinger( true, 50 );

6.4.4.5 TCP_NODELAY Socket Option

This socket option is a flag, the state of which controls whether Nagle's algorithm (RFC 896) is enabled or not. Because TCP data is sent over the network using IP datagrams, a fair bit of overhead exists for each packet, such as IP and TCP header information. If only a few bytes at a time are sent in each packet, the size of the header information will far exceed that of the data. On a local area network, the extra amount of data sent probably won't amount to much, but on the Internet, where hundreds, thousands, or even millions of clients may be sending such packets through individual routers, this adds up to a significant amount of bandwidth consumption.

The solution is Nagle's algorithm, which states that TCP may send only one datagram at a time. When an acknowledgment comes back for each IP datagram, a new packet is sent containing any data that has been queued up. This limits the amount of bandwidth being consumed by packet header information, but at a not insignificant cost—network latency. Since data is being queued, it isn't dispatched immediately, so systems that require quick response times such as X-Windows or telnet are slowed. Disabling Nagle's algorithm may improve performance, but if used by too many clients, network performance is reduced.

Nagle's algorithm is enabled or disabled by invoking the Socket.setTcpNoDelay(boolean state) method. For example, to deactivate the algorithm, the following code would be used:

// Disable Nagle's algorithm for faster response times
someSocket.setTcpNoDelay(false);

To determine the state of Nagle's algorithm and the TCP_NODELAY flag, the Socket.getTcpNoDelay() method is used:

// Get the state of the TCP_NODELAY flag
boolean state = someSocket.getTcpNoDelay();

6.4.4.6 SO_TIMEOUT Socket Option

This timeout option is the most useful socket option. By default, I/O operations (be they file- or network-based) are blocking. An attempt to read data from an InputStream will wait indefinitely until input arrives. If the input never arrives, the application stalls and in most cases becomes unusable (unless multithreading is used). Users are not fond of unresponsive applications, and find such application behavior annoying, to say the least. A more robust application will anticipate such problems and take corrective action.

NOTE

In a local intranet environment during testing, network problems are rare, but on the Internet stalled applications are probable. Server applications are not immune—a server connection to a client uses the Socket class as well, and can just as easily stall. For this reason, all applications (be they client or server) should handle network timeouts gracefully.

When the SO_TIMEOUT option is enabled, any read request to the InputStream of a socket starts a timer. When no data arrives in time and the timer expires, a java.io.InterruptedIOException is thrown, which can be caught to check for a timeout. What happens then is up to the application developer—a retry attempt might be made, the user might be notified, or the connection aborted. The duration of the timer is controlled by calling the Socket. setSoTimeout(int) method, which accepts as a parameter the number of milliseconds to wait for data. For example, to set a five-second timeout, the following code would be used:

// Set a five second timeout
someSocket.setSoTimeout ( 5 * 1000 );

Once enabled, any attempt to read could potentially throw an InterruptedIOException, which is extended from the java.io.IOException class. Since read attempts can already throw an IOException, no further code is required to handle the exception—however, some applications may want to specifically trap timeout-related exceptions, in which case an additional exception handler may be added.

try
{
      Socket s = new Socket (...);
      s.setSoTimeout ( 2000 );

      // do some read operation ....
}
catch (InterruptedIOException iioe)
{
      timeoutFlag = true; // do something special like set a flag
}
catch (IOException ioe)
{
      System.err.println ("IO error " + ioe);
      System.exit(0);
}

To determine the length of the TCP timer, the Socket.getSoTimeout() method, which returns an int, can be used. A value of zero indicates that timeouts are disabled, and read operations will block indefinitely.

// Check to see if timeout is not zero
if ( someSocket.getSoTimeout() == 0) someSocket.setSoTimeout (500);

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020